gpt4 book ai didi

assembly - 了解程序集堆栈操作

转载 作者:行者123 更新时间:2023-12-04 05:02:41 25 4
gpt4 key购买 nike

我正在裸机 ARM 上编写 sdram 测试程序。我是用 C 写的,但现在我想修改生成的程序集以防止程序使用 sdram,这意味着除其他外,没有堆栈。

最近开始学习ARM汇编,不明白编译器生成的汇编是如何使用下面代码中的堆栈的(而且我没有通过阅读ARM ARM找到答案:/)。 32位的变量值是放在栈上的,但是为什么在函数开始的时候push会保留3乘以32位呢?有人可以在这里解释堆栈操作吗?

C代码:

/* ugly to have it as global but it reduces stack usage*/                                              
unsigned int const led_port[]= {0,0,1,1,2,2,3,3,4,4};
unsigned int const led_value_on[]={0x90,0x9,0x90,0x9,0x90,0x9,0x90,0x9,0x90,0x9};
unsigned int const masks[] = {0xf0,0xf,0xf0,0xf,0xf0,0xf,0xf0,0xf,0xf0,0xf};
unsigned int const led_value_off[]={0x80,0x8,0x80,0x8,0x80,0x8,0x80,0x8,0x80,0x8};

void gbe_led_on(int i)
{
unsigned int value = 0;
phy_read(led_port[i], 0x10, &value);
value &= ~masks[i];
value |= led_value_on[i];
phy_write(led_port[i], 0x10, value);
}

生成的程序集(来自 gcc-arm-elf):
     <gbe_led_off>:
push {r4, r5, r6, lr} /* ;reserve space on the stack for 3 32 bits variables + return address */
ldr r5, [pc, #84] ; ffff1578 <gbe_led_off+0x60> /*r5=led_port (array base address) */
sub sp, sp, #8 /* sp = sp-8 (decimal 8) what does it point to??*/
ldr r4, [r5, r0, lsl #2] /* r4 = *(led_port+i)&0x00ff, (shift from 16 bits) */
add r2, sp, #8 /* r2 = sp+8 (decimal 8) why???*/
mov r6, r0 /* r6 = i */
mov r3, #0 /* r3 = 0 */
mov r0, r4 /* r0 = led_port[i]*/
str r3, [r2, #-4]! /* r3 = *(sp+8-4); update r2, to which value???*/
add r5, r5, r6, lsl #2 /* r5 = led_port[i] & 0x00ff */
mov r1, #16 /* r1 = 16 (decimal) */
bl ffff13f8 <phy_read> /* call phy_read with arguments on r0, r1, r2*/
ldr r1, [r5, #40] ; 0x28 /* r1 = masks[i] */
ldr r3, [sp, #4] /* r3 = *(sp+4) ????*/
ldr r2, [r5, #120] ; 0x78 /* r2 = led_value_on[i] */
bic r3, r3, r1 /* value &= masks[i] */
orr r3, r3, r2 /* value |= led_value_on[i] */
mov r0, r4 /* r0 = led_port[i] */
mov r2, r3 /* r2 = value */
mov r1, #16 /* r1 = 16 */
str r3, [sp, #4] /* *(sp+4) = value; why do we do that???*/
bl ffff13cc <phy_write> /* branch to phy_write with arguments on r0,r1,r2*/
add sp, sp, #8 /* sp = sp+8 restore stack pointer before pop? */
pop {r4, r5, r6, pc} /* remove 4 bytes from the stack and branch to return address */
.word 0xffff1a30

最佳答案

推送是为了保存寄存器 r4 , r5 , 和 r6所有这些都必须根据 ARM 编程模型进行保留。 lr的推送是在调用将修改它的其他函数时保留返回地址。 sub 8从堆栈中保留另外 8 字节的内存供其他变量使用( value 变量)-稍后用于 str r3, [2, #-4]线。另外,支线链接blphy_readphy_write也可能正在修改堆栈空间,因此您的堆栈内存问题可能比您想象的要大。此外,您最后一次关于 4 个字节的流行评论是不正确的 - 它释放了 16 个字节的空间。

现在,您将有哪些可用的 RAM 资源可供使用?您需要一些东西,否则您的 unsigned int value更不用说你的电话了。你必须有可用的东西。如果这样做,您可以通过链接描述文件和 section 告诉您的 C 程序有关它的信息。指令,省去汇编程序的麻烦。

关于assembly - 了解程序集堆栈操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15937634/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com