1

I'd like to print the counter of a loop (0 --> 4). In the code below diff is the ASCII number of '0' character, max the times the loop repeats, count the counter and p is the variable that contain the character.

.data

.text

.global main

diff    =   48
max     =   5   

count:  .byte   0
p:      .long   0

main:

compare:
    cmpb    $max,count    # if counter is equal or above max
    jae     end           # jump to end

    movl    $4,%eax       # write
    movl    $1,%ebx       # stdout
    xor     %ecx,%ecx     # reset ecx
    addb    $diff,%cl     # add ASCII number of '0'
    addb    count,%cl     # add value of counter
    movb    %cl,p         # move ASCII value of the counter
    movl    $p,%ecx       # move the number to third argument of write
    movl    $4,%edx       # size of long
    int     $0x80         # interrupt

    movb    count,%al     # move value of the counter to al
    inc     %al           # increment al
    movb    %al,count     # move value of al to counter
    jmp     compare       # always jump to compare

end:
    movl    $1,%eax       # exit
    movl    $0,%ebx       # exit(0)
    int     $0x80         # interrupt

It doesn't work. gcc doesn't give me errors, but executing it gives a core dump. Why?

untitled
  • 389
  • 4
  • 13
  • 1
    Another word of advice: if you're learning assembly, you might find it more advantageous to study 64-bit rather than 32-bit x86 assembly, as the majority of systems these days are 64-bit. – Nate Eldredge Jan 30 '16 at 18:24
  • I'm not expert about Assembly language at all. Would you suggest me some guides? – untitled Jan 30 '16 at 18:29
  • I don't know any off the top of my head. Maybe someone else can help. – Nate Eldredge Jan 30 '16 at 18:31
  • There are some links in the x86 tag wiki. http://stackoverflow.com/tags/x86/info. I think the tutorial links are all pretty old, though. I'm sure there are tutorials that use AT&T syntax, but IDK if any of them are linked on the wiki. I don't know of any myself, since I taught myself asm from compiler output, manuals, and reference guides and maybe an old book when I was very first learning a few things, but not any tutorials that I remember. – Peter Cordes Jan 31 '16 at 14:08
  • Anyway, your loop does some weird stuff: why not just keep the loop counter in a register that the `write` system call won't destroy, instead of loading/storing it every time? And if you are going to load/store it, don't load it twice (once before increment, then again in the compare instruction at the top of the loop). Put the conditional branch at the bottom of the loop (like a C `do{}while()` loop). Either `inc count` to increment a memory operand, or (much better) keep the counter in a reg that survives across the `int 0x80`: i.e. any register except the return value in `eax` – Peter Cordes Jan 31 '16 at 14:33
  • See http://stackoverflow.com/a/2709009/224132: Linux `int 0x80` system calls save/restore all registers (except the return value), not just the usual call-preserved registers. – Peter Cordes Jan 31 '16 at 14:34
  • What register can I store the counter in? – untitled Jan 31 '16 at 18:05

1 Answers1

4

Your variables count and p are defined after the .text directive, which means they are in the text section. This section is supposed to be used for code and is read-only. So attempting to write to these locations causes a segfault.

You probably wanted to define them following the .data directive.

After fixing this, it looked like the program works, but actually there is another bug. On each loop iteration you invoke write with 4 bytes, an entire long. The upper bytes are 0. So instead of writing one byte, ascii 0 (0x30), you write 4 bytes (0x30 0x00 0x00 0x00). Your program outputs a total of 20 bytes instead of 5.

You probably want to just write one byte. In that case you would want to set %edx to 1 when invoking write. And in that case, p can just be a .byte instead of .long.

By the way, if you run this under a debugger (such as gdb), you will immediately see which instruction faulted. If you didn't do that, you should! Knowing how to use a debugger is essential for a programmer in any language, but most especially assembly.

If you did, it would have been nice to include the information in your question.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82