Reputation: 339
I am currently writing some stuff in MIPS-Assembler and I have some trouble: I wrote this function:
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
if I run this program the instruction add $a1, $s0, $zero is skipped and I don't know why...
Another funny thing, if I debug this program with GDB:
main:
addi $t0, $zero, 3
addi $t0, $zero, 3
addi $t0, $zero, 3
jal READ_FLOAT
jal PRINT_FLOAT
and set a breakpoint at main, the breakpoint is set at the third "addi $t0, $zero, 3" What happens here?
Upvotes: 3
Views: 2181
Reputation: 9466
When you set a breakpoint at function and there is no debug information available, gdb tries to set a breakpoint after a function prologue.
Gdb analyzes machine instructions to detect a prologue. "addi $sp, $sp, -4" looks like it might be recognized as prologue (but I'm no MIPS expert so I may be wrong).
Enable debug information when assembling/linking and gdb should have more information about frames available.
You can also disassemble your main (disas main) and set a breakpoint to address of first instruction (like this: break *0xabcdef) instead of "break main".
Upvotes: 0
Reputation: 33601
gdb
is a high level source debugger, so it's a little harder to deal with asm on an instruction by instruction basis.
For example, to step through C code, normally the "s" [step] command is used. But, gdb
will "step across" any asm sequence that it considers to be part of a single C statement.
To step individual asm instructions, you want the "si" [step instruction] command. See help si
Likewise, when setting breakpoints, you want to use a modified form of the command. break * whatever
to set a breakpoint at address whatever
. See help break
To be able to get the correct addresses, you may need to disassemble a bit, so see help disassemble
and help x
. To disassemble a single instruction, x/i ...
also works.
As, dwelch pointed out, your assembler may "get cute" and reorder things. By having gdb
do the disassembly, you'll be able to see whether this has happened or not. And, if branch delay slots are enabled/active on the actual processor, you'll need to account for them. For example, when running with a simulator such as spim
or mars
, use of branch delay slots is configurable [and default off], but with a real processor, there may be no choice.
if I run this program the instruction add $a1, $s0, $zero is skipped and I don't know why...
That may be why you think the add $a1,$s0,$zero
instruction is being skipped. gdb
[with "step"] will treat the following as a single block:
la $a0,strFloat
add $a1,$s0,$zero
jal printf
the breakpoint is set at the third
addi $t0, $zero, 3
Once again, for the same reason as above. Use the alternate form of the breakpoint command.
Upvotes: 3