This sort of stuff is why I love being a software engineer. The lower you go it starts to feel like an expedition into the mysterious caves under a city. Great job, you got a new sub.
@@LowLevelLearning Hi, I just found your channel, and love it! I have been a software developer for 22 years, started as a Delphi developer, then PHP, JS, TS in the meantime, recently C and C++ for Arduino or ESP32, as a hobby, and I realized, that I like low level programming, and assembly the most. I started machine code in the C64 era, so I know everything about 6502 processor, interrupts, memory handling, memory mapped registers, remember many hexa code of every assembly opcodes, addressing types, can write any code in 8bit. I wrote basic extensions for C64 BASIC, even framework for a window OS system like GEOS on C64, font editor in half basic and assembly, screen interrupts to use more than 16 color on screen, etc. I think I should go back to low level programming, because i feel it closer to me than CSS rules and flexbox layout. Is there any demand for low level programmers recently? Is there any point to switch career to this? I'd have many questions...
I have been teaching myself about programming/web development for years, and I feel like this is the time to start my journey closer to the machine and understand what is really happening You deserved a new sub
Cool video! Some ideas of what I think would be interesting: 1. Seeing how a program in high-level language (simple hello world or some file manipulation) gets actually executed on a CPU. It would be extra nice if the high-level language was something with VM in between, like Java or C# (.NET). 2. Explanation of how device drivers work in Linux. 3. Kernel stuff - explained in a way that is easy to understand 4. How the multithreaded or async code is executed on the CPU (multiple cores, multiple threads) - that would be interesting 5. Comparing different architectures of CPU - it would be great to see you giving an overview of CPUs from very simple ones (some AVR, or old 6502, or something even simpler), up to what we have today. I think that would make it much easier to understand why today's architecture are so complicated.
@@mnj1 It's not a VM language because the IL gets JIT-compiled to native machine code at runtime. This only happens once and the resulting code is not run in a VM. It's native machine code. At that point it's the same as compiled C, only with less optimisations because the JIT compiler has to run very quickly. There is no VM involved whatsoever. Java runs a VM, C# does not.
Last night I finally had the opportunity to try this out on my Pi and am happy with the results. I noticed two things, e.g. that you use „svc“ in later videos, which was „swi“ here (is apparently the same) and that you always start with the r7 (later x8) value and then type out the arguments. I don‘t know about coding conventions yet, but noticed that the order doesn’t technically matter as the execution only happens at swi/svc. When I stepped through this with GDB, I noticed that „pc“ when moved into a register, already points to the next instruction. I don‘t remember if you talk about this in one of your following videos, please excuse if this is the case and my suggestion to cover this is redundant. Thanks again, your content is really helpful.
Super cool to know. I've been exploring x86 as I'm trying to position myself in a better place for a career in reverse engineering. Since Microsoft is showing its biggest push for ARM yet, I'm interested in understanding ARM architecture as well.
You need more followers so that you are more visible :) Glad the algorithm go it right for me. I learned about assembler but never did anything useful with it so it faded away. Maybe you could present a use case scenario where you use assembler to get some use or function out of an older ARM tablet or phone that is no longer fast enough for Windows/Android and does not have Linux support?
I still have an iPhone 4 in the electronics spare parts bin that powers on and an iPhone 5 that is still booting too. Several Windows tablets, and a pile of Pi's. Just sayin :)
14:27 BTW, I got interested in the instruction "mov r0, #65". Why is the 65 a funny number in embedded programming? Once it's in a decimal format, it's the equivalent to 'A', right?
That was really easy to understand. My only small quip is that you are pretty quiet - I had to turn the volume up quite a bit - perhaps consider getting a cheap usb studio mic (~$100)?
I would argue x86 is no more complicated for basic things at least. With x86_64, arguably even simpler. Being able to access memory directly without a load, and the sys call instruction, I would think easier than having to think about load/store and software interrupts.
I have multiple questions : 1- why do we need to exit ? I can understand that the system call is the interface to the kernel? where is the kernel we just wrote simple bare metal sw ? so which kernel do we interface with it and caused this crash? 2 - ldr r1 =message do we need the address of memory location to be loaded to the register or the data it self? 3- which .txt or .data this code is linked to? which memory region do we have linker?
I think you are confused. He is writing a program for a computer running on ARM processor, eg Raspberry Pi. It is not for a microcontroller where system call is not required.
So just to clarify, when you do software interrupt 0, that's not hard-coded in ARM, right? That's just how the Linux kernel implements syscalls? So at some point during its startup, the Linux kernel defines an interrupt handler for swi 0 that checks register 7 and performs whatever routine you requested? Or does the ARM specification require that swi 0 be the way to handle calls into the kernel?
Thanks for watching! I'm making these ARM tutorials in a Virtualbox VM, but they will also work on a Raspberry Pi. Check the pinned comment for instructions to compile natively on an ARM platform
I use the program QEMU to emulate an ARM processor and run my programs. If you use a Raspberry Pi you dont need to do this. In either scenario the code that gets created is ARM
I was unable to install 'gcc-arm-linux-gnueabi' using 'apt' with the error 'No installation candidate'. Spent 20 minutes or so searching for alternate packages only to realize 'apt-get' was all I needed.
Does anyone know if there is a RasPi equivalent of the old style C64 monitor programs ? Tried out gdb, but it's not too friendly. (at least for me, today)
What is he writing the code in for it to compile? I've searched all over the internet and everything is either wrong, outdated, missing, or for a OS that I'm not using.
3:20 "Step 1... run this command". I can't read any of that. Is it written down somewhere? Out of curiosity, how big was the monitor used to make this, and what resolution was it set to?
If I’m running windows then I need a VM to work in a Linux environment? Openbox or Proxmox. If I’m running Linux in a VM should I just run an ARM version? Manjaro? What is the HEX editor you ran x??, the screen was too blurry to make it out.
You do need to be in a VM to do this. It doesn't have to be an ARM VM, the commands I use do emulation so you can run ARM binaries in an Intel environment. The command was xxd. Thanks for watching! :)
I've done a fair bit of C with STM32, been wanting to explore writing some raw assembly for it since I have a ton of STM32s lying around with nothing to do. It just pains me that ARM syntax is right-to-left like NASM. AT&T syntax is way more intuitive to me, but oh well, not that big of a deal :b
The thing I'm grappling with is what is linux kernal loaded as boot vs. what is already in a raspberry pi (zero) rom? and how is that same or different when using qemu
The weirdest part about trying to follow is "oh, my windows doesn't have sudo apt get arm or other assembly packages and doesn't know what to do with .elf even though with normal assembly it compiles".
"we assembled our assembly into machine code. We compiled it into a runable .elf" I don't understand the last part. I though compilers also output machine code. What's the difference between compiler output(ed) machine code and the elf?
at 13:53 i was expecting to see "mov r2, #14" instead of "mov r2, #13" because of the implicit null terminator "\0". how is it that assembly does not have this annoying behaviour that c is so famous for?
It's not always ` , ` (this is Intel syntax, yuck!) But it merely depends on the opcode! For instance: `ldr r2, [r0]` loads the register r2 with the value at the memory address found in r0. (ie , ) `str r2, [r1]` stores the value of r2 at he memory address found in r1. (ie , )
Great tutorial, the only thing that is confusing for me, is why length of message string is equal 13 not 14? From the way you count, I assume that you interpret " " as string of length 1, but why is that? Thanks for help in advance :)
Ah, I probably should have explained this a little bit. When you see \ followed by a character in a string, that's called an "escape character". Escape characters are used to represent characters that the keyboard cannot type or that would otherwise be misrepresented if typed manually. When the assembler interprets that string, it treats the sequence as ONE character, to represent the enter key. I hope that makes sense. Thanks for watching!
@@LowLevelLearning Yes it does, i'm familiar with programming in c and c++, but for some reason I thought that assembler is more ... I don't know, literal? anyway, thanks :)
Thanks great video but quick questions: What environment IDE are you using ? What tools (opensource) do you recommend to use the compiler/drbuger in GUI mode ? I’m currently using docker for ARM/asm-32bit but have problem Docker blocks the debugger GDB, so I’m testimg a GDB SERVER with a C.H.I.P. Online, have 38 students not all have Rpi so we virtualization QEMU, but is a pain working GUI IDE on 1/8 of the screen So thats why the questions!
Thank you for great video. Just add: that arm executable could run on x86 linux without calling `qemu-arm' directly, via binfmt_misc mechanism: % uname -p x86_64 % file 001.elf 001.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped % ./001.elf zsh: exec format error: ./001.elf % sudo apt install qemu-user-static ... % ./001.elf Hello, World % hostnamectl status | tail -3 Operating System: Ubuntu 21.04 Kernel: Linux 5.11.0-25-generic Architecture: x86-64
How is the information stored? The program gets compiled into assembly, .elf. This elf file is stored either in memory or on the HDD. Is it in the storage medium as hex?
That should also be Pico compatible as well. M0 are arm cores, there is no OS on there, and it’s the same eabi (Embedded Application Binary Interface). (This is formatting (eg. gcc-arm-none-eabi) known as a “triple target”). I’m basically hoping that this will each me some PIO programming that has to be done in ARM Assembly.
Update to my last comment Thanks to @simvalue changed " mov r0, #0x01 " -to- " mov x0, #0x01 " no error message Can you please explain in a tutorial, whats happening? Thank You.
quite hard to find a way where it can be used. you can't just launch an executable arm file on android. in windows or especially dos you can write a raw code for execution but for android you need apps for create apk and when it's getting installed as i know its also compiling the code. so outputting hello world in a linux console... it doesnt have any practical sense
LDR?? And then an '=' before message?? What the heck? At first I was starting to like ARM assembly until this happened. Why isn't this just "mov r1, message". Mov should work like this: mov r1, message to just load the register with the address of the text (for this case), or mov r1, byte ptr [message]. for example, if you wanted to simply load the 'H' of 'Hello World' into the register. Of course, if calculations are involved, you have to use LEA in x86 asm. But there are no calculations of getting the address here. Shouldn't need a separate op code.