Assembly 汇编程序-跳过指令
我目前正在MIPS Assembler中编写一些东西,遇到了一些问题: 我写了这个函数:Assembly 汇编程序-跳过指令,assembly,gdb,mips,skip,Assembly,Gdb,Mips,Skip,我目前正在MIPS Assembler中编写一些东西,遇到了一些问题: 我写了这个函数: PRINT_FLOAT: addi $sp, $sp, -4 #stackpointer um ein wort weiterrücken sw $ra, 0($sp) #rücksprungadresse auf stack speichern la $a0, strFloat add $a1, $s0, $z
PRINT_FLOAT:
addi $sp, $sp, -4 #stackpointer um ein wort weiterrücken
sw $ra, 0($sp) #rücksprungadresse auf stack speichern
la $a0, strFloat
add $a1, $s0, $zero
jal printf
lw $ra, 0($sp) #rücksprungadresse aus stack holen
addi $sp, $sp, 4 #stackpointer um ein wort zurückrücken
jr $ra
如果我运行这个程序,将跳过指令add$a1、$s0、$zero,我不知道为什么
另一件有趣的事,如果我用GDB调试这个程序:
main:
addi $t0, $zero, 3
addi $t0, $zero, 3
addi $t0, $zero, 3
jal READ_FLOAT
jal PRINT_FLOAT
并在main处设置断点,断点设置在第三个“addi$t0,$zero,3”
这里发生了什么?gdb是一个高级源代码调试器,因此在逐个指令的基础上处理asm有点困难 例如,要单步执行C代码,通常使用“s”[step]命令。但是,
gdb
将“跨过”它认为是单个C语句一部分的任何asm序列
要单步执行单个asm指令,需要使用“si”[step指令]命令。请参阅帮助si
同样,在设置断点时,您希望使用修改后的命令形式break*which
在地址which
设置断点。请参见帮助中断
为了能够获得正确的地址,您可能需要进行一些反汇编,因此请参阅帮助反汇编
和帮助x
。要反汇编单个指令,x/i…
也可以工作
正如德韦尔奇指出的,你的汇编程序可能会“变得可爱”并重新排序。通过让gdb
进行反汇编,您将能够看到是否发生了这种情况。而且,如果在实际处理器上启用/激活了分支延迟插槽,则需要考虑它们。例如,当使用诸如spim
或mars
之类的模拟器运行时,分支延迟槽的使用是可配置的[并且默认为关闭],但对于真正的处理器,可能没有选择
如果我运行这个程序,将跳过指令add$a1、$s0、$zero,我不知道为什么
这可能就是您认为add$a1、$s0、$zero
指令被跳过的原因<代码>gdb[带“步骤”]将以下内容视为单个块:
la $a0,strFloat
add $a1,$s0,$zero
jal printf
断点设置在第三个addi$t0、$0、3
同样,出于与上述相同的原因。使用breakpoint命令的另一种形式。当您在函数中设置断点,并且没有可用的调试信息时,gdb会尝试在一个断点之后设置断点 Gdb分析机器指令以检测序言。“addi$sp,$sp,-4”看起来像是开场白(但我不是MIPS专家,所以我可能错了) 在组装/链接时启用调试信息,gdb应该有关于可用帧的更多信息
您还可以反汇编main(disas main)并将断点设置为第一条指令的地址(如:break*0xabcdef),而不是“break main”。您正在使用优化进行组装吗?这对于三个
addi
语句是有意义的,因为它们都做相同的事情,使得其中两个多余。您的汇编器是否将add放入分支延迟槽?您的反汇编对此代码显示了什么?以前你必须明确地做这件事,上次我使用gnu汇编程序时,它只是简单地将前面的指令与分支交换,必须明确地告诉它不要这样做。或者告诉它该体系结构没有分支延迟槽。基于MIPS disassemby,我回顾了“addi$sp,$sp,-4”将堆栈大小增加了4个字节。通常在函数“addi$sp,$sp,4”的末尾有一个补充行,以将堆栈减少相同的数量。