我有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呢?
答案 0 :(得分:2)
ldr r0, =eoa
和ldr r1, =array
是pseudo 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");