GDB ARM汇编程序指令是以我不了解的方式编译的

时间:2018-01-03 18:08:29

标签: gcc assembly arm qemu

我有ARM汇编源代码:

    .global _start
    .text

entry:  b _start            
array:  .byte 10, 20, 25    
eoa:                        

    .align                  

_start:     

    ldr r0, =eoa            
    ldr r1, =array        
    mov r3, #0            

loop:   

    ldrb r2, [r1], #1                           
    add r3, r2, r3                                     
    cmp r1, r0                                          
    bne loop                

stop:   b stop       

这是一个简单的数组之和。所以现在我在Linux终端中使用这一系列命令编译它:

arm-none-eabi-as -o program.o program.s
arm-none-eabi-ld -Ttext=0x0 -o program.elf program.o
arm-none-eabi-objcopy -O binary program.elf program.bin

如果我检查编译文件的大小:

ls -l
-rwxrwxrwx 1 ziga ziga       48 Nov 22 12:38 program.bin
-rwxrwxrwx 1 ziga ziga    66396 Nov 22 12:37 program.elf
-rwxrwxrwx 1 ziga ziga      864 Nov 22 12:36 program.o
-rwxrwxrwx 1 ziga ziga     1952 Jan  3 18:50 program.s

我看到如果我从可执行文件.elf中删除标头,我会得到.bin个文件,该文件的长度恰好为48字节。这意味着它可以有12个ARM指令吗?

现在我准备16KiB FLASH图像,将.bin文件复制到FLASH图像并在connex板上启动QEMU模拟,如下所示:

dd if=/dev/zero of=flash.bin bs=4096 count=4096
dd if=program.bin of=flash.bin conv=notrunc
qemu-system-arm -M connex -nographic -serial /dev/null -pflash flash.bin 

在模拟器中,如果我使用info registers检查寄存器,我得到:

R00=00000007 R01=00000007 R02=00000019 R03=00000037
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000024
PSR=600001d3 -ZC- A svc32
FPSCR: 00000000

看起来很好,因为寄存器R03包含十六进制值0x37,它是十进制的55,它是我用命令.byte 10, 20, 25提供的数组的正确总和。

我不明白的是,如果我使用xp /12wi 0x0转储前12个命令,我明白了:

0x00000000:  ea000000      b    0x8
0x00000004:  0019140a      andseq   r1, r9, sl, lsl #8
0x00000008:  e59f0018      ldr  r0, [pc, #24]   ; 0x28
0x0000000c:  e59f1018      ldr  r1, [pc, #24]   ; 0x2c
0x00000010:  e3a03000      mov  r3, #0  ; 0x0
0x00000014:  e4d12001      ldrb r2, [r1], #1
0x00000018:  e0823003      add  r3, r2, r3
0x0000001c:  e1510000      cmp  r1, r0
0x00000020:  1afffffb      bne  0x14
0x00000024:  eafffffe      b    0x24
0x00000028:  00000007      andeq    r0, r0, r7
0x0000002c:  00000004      andeq    r0, r0, r4

我如何证明命令2-4和11-12对自己是合理的?他怎么算我的总和55呢?

2 个答案:

答案 0 :(得分:2)

ldr r0, =eoaldr r1, =arraypseudo instruction,因为它们不在ARM instruction set中。它们不能直接转换为ARM汇编程序。当编译器看到这些指令时,它会将它们转换为最有效的指令。

如果你看看你的反汇编:

0x00000008: e59f0018 ldr r0, [pc, #24] ; 0x28 0x0000000c: e59f1018 ldr r1, [pc, #24] ; 0x2c (...) 0x00000028: 00000007 andeq r0, r0, r7 0x0000002c: 00000004 andeq r0, r0, r4

你可以看到编译器你的数组的基地址(即:0x4因为它是32位对齐)和数组的结尾(即:数组的基地址+ 3字节= 0x7)分别在偏移量0x28处(在0x8 + 0x24之前pc和在0xc + 0x24之前的0x2c(pc)。

注意:也可以将ldr rN, =#immediate编码到单个装配线中。 ARM指令集支持16位立即值(即:从0到65535)。见ARM instruction set的第2页。编译器将尝试使用最有效的编码。

答案 1 :(得分:2)

实际上将adr rN, label替换为ADR会更有效率! 00000000 <entry>: 0: eafffffe b 8 <_start> 00000004 <array>: 4: 140a .short 0x140a 6: 19 .byte 0x19 00000007 <eoa>: ... 00000008 <_start>: 8: e24f0009 sub r0, pc, #9 c: e24f1010 sub r1, pc, #16 10: e3a03000 mov r3, #0 00000014 <loop>: 14: e4d12001 ldrb r2, [r1], #1 18: e0823003 add r3, r2, r3 1c: e1510000 cmp r1, r0 20: 1afffffb bne 14 <loop> 00000024 <stop>: 24: eafffffe b 24 <stop> 使用标签形成PC相对地址。您的代码将构建为:

ldr r0, =eoa            
ldr r1, =array 

注意:我对原始代码所做的唯一更改是替换:

adr r0, eoa            
adr r1, array        

人:

System.setProperty("webdriver.ie.driver","D:\\Automation\\Drivers\\IEDriverServer.exe");
DesiredCapabilities capabilities = DesiredCapabilities.internetExplorer();
capabilities.setCapability("ignoreZoomSetting", true);
WebDriver driver = new InternetExplorerDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
Thread.sleep(3000);
driver.get("http://google.co.in");