There are two basic ways to inspect a running program: print out a bunch of debug statements or run it through a debugger. Since I don’t yet know how to print out my own statements in ARM64 debugging (I’ll get there soon) I want to use the debugger to see my code in action.
First, a little tweak to the Makefile rule to build the code. I hard code in the -g flag to include debugging symbols in the executables. This is learning code, and I am not going to be running it in stripped mode, so no need for Makefile variables.
%: %.s as -g -o $@.o $< ld -o $@ $@.o |
I’ve got a simple assembly program that adds the value and 2 together. It looks like this:
.global _start _start: MOV W0, #2 ADD W0, W0, #1 MOV X8, #93 SVC 0 |
Compile it:
$ make adder as -g -o adder.o adder.s ld -o adder adder.o |
OK, let’s fire up the assembler. Here’s the start of the session slightly edited
$ gdb adder GNU gdb (GDB) Fedora 11.1-2.fc34 ... Reading symbols from adder... (gdb) list 1 .global _start 2 3 _start: 4 MOV W0, #2 5 ADD W0, W0, #1 6 7 8 MOV X8, #93 9 SVC 0 (gdb) break _start Breakpoint 1 at 0x400078: file adder.s, line 4. (gdb) run Starting program: /home/ayoung/devel/asm/adder Breakpoint 1, _start () at adder.s:4 4 MOV W0, #2 (gdb) |
Now we are at the start of the program, on the first line of code. It has not yet been executed. What is the pre-value of the W0 register?
(gdb) i r w0 w0 0x0 0 |
Now make single step, and we should be able to see the value get stored in the register. The following step shows the addition. The final step shows the completion of the program
(gdb) n 5 ADD W0, W0, #1 (gdb) i r w0 w0 0x2 2 (gdb) n 8 MOV X8, #93 (gdb) i r w0 w0 0x3 3 (gdb) n 9 SVC 0 (gdb) step [Inferior 1 (process 608616) exited with code 03] |
Note that I used n for next in most cases, but I used step in the last. Why? I wanted to see if I could follow the function call (I couldn’t) when I called svc 0. In C code, the next command will skip over function calls, but the step command will step into them. In this case, they behaved the same