ARM 汇编程序的异常行为
Unusual behavior of ARM assembly program
我一直在为简单的表达式编写 JIT ARM 编译器。我的即时编译器获得了将在表达式和表达式本身中使用的函数和变量的地址。并生成计算表达式的 ARM 代码。
这是我的编译器对表达式 inc(1) + 1
:
的输出
start:
push {r4} //saving r4
ldr r0, [pc] //writing the constant into r0
b skip0 //skipping data line
.word 0x1
skip0:
push {r0} //saving the constant
pop {r0} //fucntion time. Let's pop the argument
ldr r4, [pc] //Let's get function address
b skip1 //skipping data line
.word 0x13050
skip1:
bx r4 //jumping to function
push {r0} //saving the output of it
ldr r0, [pc] //writing the constant into r0
b skip2 //skipping data line
.word 0x1
skip2:
push {r0} //saving the constant
pop {r0-r1} //getting function result and the constant
add r0, r1, r0 //adding them to each other
push {r0} //saving the result
pop {r0} //work done, popping the result to r0 in order to return it
pop {r4} //placing r4 back
bx lr
inc(x)
是一个外部函数,只是 returns ++x
。 0x13050
是函数执行时的地址。
问题是 - 输出是 2,但它必须是 3。我找不到错误,你能帮我吗?
有趣的事实:如果我将 bx
更改为 blx
,我会遇到段错误
答案在最后一行:blx
覆盖 lr
并且由于您在开始时没有保留 lr
,所以最后的 bx lr
会导致分支回到 blx r4
之后的行 push {r0}
,从而导致无限循环。
而且由于每次迭代弹出的次数比推送的次数多,堆栈指针有时会指向无效地址 => segfault
使用 bx r4
时,子函数 inc(x)
不会 return 您的函数,而是 return 值 2 的调用函数以及不正确的堆栈指针。
start:
push {r4, lr} //saving r4 AND lr
ldr r0, [pc] //writing the constant into r0
b skip0 //skipping data line
.word 0x1
skip0:
push {r0} //saving the constant
pop {r0} //fucntion time. Let's pop the argument
ldr r4, [pc] //Let's get function address
b skip1 //skipping data line
.word 0x13050
skip1:
blx r4 //jumping to function
push {r0} //saving the output of it
ldr r0, [pc] //writing the constant into r0
b skip2 //skipping data line
.word 0x1
skip2:
push {r0} //saving the constant
pop {r0-r1} //getting function result and the constant
add r0, r1, r0 //adding them to each other
push {r0} //saving the result
pop {r0} //work done, popping the result to r0 in order to return it
pop {r4, pc} //placing r4 back AND return
我一直在为简单的表达式编写 JIT ARM 编译器。我的即时编译器获得了将在表达式和表达式本身中使用的函数和变量的地址。并生成计算表达式的 ARM 代码。
这是我的编译器对表达式 inc(1) + 1
:
start:
push {r4} //saving r4
ldr r0, [pc] //writing the constant into r0
b skip0 //skipping data line
.word 0x1
skip0:
push {r0} //saving the constant
pop {r0} //fucntion time. Let's pop the argument
ldr r4, [pc] //Let's get function address
b skip1 //skipping data line
.word 0x13050
skip1:
bx r4 //jumping to function
push {r0} //saving the output of it
ldr r0, [pc] //writing the constant into r0
b skip2 //skipping data line
.word 0x1
skip2:
push {r0} //saving the constant
pop {r0-r1} //getting function result and the constant
add r0, r1, r0 //adding them to each other
push {r0} //saving the result
pop {r0} //work done, popping the result to r0 in order to return it
pop {r4} //placing r4 back
bx lr
inc(x)
是一个外部函数,只是 returns ++x
。 0x13050
是函数执行时的地址。
问题是 - 输出是 2,但它必须是 3。我找不到错误,你能帮我吗?
有趣的事实:如果我将 bx
更改为 blx
,我会遇到段错误
答案在最后一行:blx
覆盖 lr
并且由于您在开始时没有保留 lr
,所以最后的 bx lr
会导致分支回到 blx r4
之后的行 push {r0}
,从而导致无限循环。
而且由于每次迭代弹出的次数比推送的次数多,堆栈指针有时会指向无效地址 => segfault
使用 bx r4
时,子函数 inc(x)
不会 return 您的函数,而是 return 值 2 的调用函数以及不正确的堆栈指针。
start:
push {r4, lr} //saving r4 AND lr
ldr r0, [pc] //writing the constant into r0
b skip0 //skipping data line
.word 0x1
skip0:
push {r0} //saving the constant
pop {r0} //fucntion time. Let's pop the argument
ldr r4, [pc] //Let's get function address
b skip1 //skipping data line
.word 0x13050
skip1:
blx r4 //jumping to function
push {r0} //saving the output of it
ldr r0, [pc] //writing the constant into r0
b skip2 //skipping data line
.word 0x1
skip2:
push {r0} //saving the constant
pop {r0-r1} //getting function result and the constant
add r0, r1, r0 //adding them to each other
push {r0} //saving the result
pop {r0} //work done, popping the result to r0 in order to return it
pop {r4, pc} //placing r4 back AND return