How to run a single line of assembly, then see [R1

2019-01-12 12:24发布

I'm trying to teach myself assembly. I've got years and year of experience with C, Java and Python- but I cant make ANY headway here and I'm about to give up.

So, I downloaded uVision4, and assumed I could just write a basic assembly program:

MOV R1,  #0x7F0E0C2D
MOV R3,  #0x1048B3C5
ADCS  R1, R3, ROR #0x18
END

So, establish two variables, do an operation, done. Check the Registers for output and debugger for condition flags, surely.

Apparently, this is impossible.

I create the text file, write my code, save as a .asm file, then try to build-

It hates that.

Okay, so I create a new project, add the .asm file,

And it refuses, demanding I apparently write an entire device driver to do a god damn hello world.

How can I run a simple couple lines of code to start learning?

标签: assembly arm
1条回答
▲ chillily
2楼-- · 2019-01-12 12:28

I do stuff like this all the time on my x86 desktop, using gdb to single-step code. Usually with x86 instructions, but it's doable for ARM cross-development, too. Build with gcc -nostdlib foo.S, and it should set the default entry point to the beginning of your .text section. You do get a warning from the linker, though:

$ arm-linux-gnueabi-gcc -nostdlib arm-simple.S 
/usr/lib/gcc-cross/arm-linux-gnueabi/5/../../../../arm-linux-gnueabi/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000010098

I had to modify your source for it to assemble. Here's my arm-simple.S:

.globl _start                                                                                                                                                       
_start:                        @ make debugging easier to have a symbol name                                                                                        

ldr   R1,  =#0x7F0E0C2D       @ ARM immediate constants can't be arbitrary 32-bit values.  Use the ldr reg, =value pseudo-op, which in this case assembles to a PC-relative load from a nearby literal pool.  Often it can use mov reg, #imm or movn reg, #imm
ldr   R3,  =#0x1048B3C5
ADCS  R1, R3, ROR #0x18

@END  This isn't an instruction.

Then you can use gdb and set a breakpoint at the first instruction, run it, and single step.

You can even do this in a cross-development environment, with a few wrinkles.


In one terminal, run QEMU on your binary, waiting for a debugger connection:

$ arm-linux-gnueabi-gcc -g -nostdlib arm-simple.S
$ qemu-arm -g 12345 ./a.out                    # user-mode emulation, waiting for gdb to connect

Use -mcpu=something for gcc, and -cpu model for qemu if you want to be specific.


In another terminal, run ARM gdb (in my case, from Ubuntu's gdb-arm-none-eabi package, since they Ubuntu doesn't distribute a arm-linux-gnueabi-gdb cross-ARM-gdb package for x86).

TODO: try gdb-multiarch. Regular gdb on an x86 desktop can only debug x86 binaries, so you definitely can't use that.

$ arm-none-eabi-gdb ./a.out          # give the gdb client the same binary to read symbols / debug info
(gdb) target remote localhost:12345
(gdb) layout asm
(gdb) layout reg
(gdb) si               # single step by instruction, not source line
(gdb) si

Then gdb shows:

+--Register group: general-----------------------------------------------------------------------------------------------------------------------------------------+
|r0             0x0      0                             r1             0x7f0e0c2d       2131627053            r2             0x0      0                             |
|r3             0x1048b3c5       273200069             r4             0x0      0                             r5             0x0      0                             |
|r6             0x0      0                             r7             0x0      0                             r8             0x0      0                             |
|r9             0x0      0                             r10            0x100ac  65708                         r11            0x0      0                             |
|r12            0x0      0                             sp             0xf6ffea40       0xf6ffea40            lr             0x0      0                             |
|pc             0x100a0  0x100a0 <_start+8>            cpsr           0x10     16                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
   ----------------------------------------------------------------------------------------------------------------------------------------------------------------+
   |0x10098 <_start>        ldr    r1, [pc, #4]    ; 0x100a4 <_start+12>                                                                                           |
   |0x1009c <_start+4>      ldr    r3, [pc, #4]    ; 0x100a8 <_start+16>                                                                                           |
  >|0x100a0 <_start+8>      adcs   r1, r1, r3, ror #24                                                                                                             |
   |0x100a4 <_start+12>     svcvc  0x000e0c2d                                                                                                                      |
   |0x100a8 <_start+16>     subne  r11, r8, r5, asr #7                                                                                                             |
   |0x100ac                 andeq  r1, r0, r1, asr #18                                                                                                             |
   |0x100b0                 cmnvs  r5, r0, lsl #2                                                                                                                  |
   |0x100b4                 tsteq  r0, r2, ror #18                                                                                                                 |
   |0x100b8                 andeq  r0, r0, pc                                                                                                                      |
   |0x100bc                 subseq r3, r4, r5, lsl #10                                                                                                             |
   |0x100c0                 tsteq  r8, r6, lsl #6                                                                                                                  |
   |0x100c4                 andeq  r0, r0, r9, lsl #2                                                                                                              |
   |0x100c8                 andeq  r0, r0, r12, lsl r0                                                                                                             |
   |0x100cc                 andeq  r0, r0, r2                                                                                                                      |
   |0x100d0                 andeq  r0, r4, r0                                                                                                                      |
   +---------------------------------------------------------------------------------------------------------------------------------------------------------------+
remote Remote target In: _start                                                                                                              Line: 6    PC: 0x100a0 
(gdb) si

It highlights the last register(s) modified, which is pretty great.

It seems to be too old to decode flags symbolically, though. modern x86 gdb does that.

查看更多
登录 后发表回答