praetorianer777
praetorianer777

Reputation: 339

Assembler - skipping instructions

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

Answers (2)

dbrank0
dbrank0

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

Craig Estey
Craig Estey

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

Related Questions