Search code examples
linuxassemblyx86gnu-assembleratt

Assembly program to write character from stack


I am trying to write a test program in AT&T syntax assembly that pushes the ascii value of some characters to the stack, then prints them. My code is as follows:

.text
.global main
main:
    push $0
    push $10
    push $65
    mov $4,%eax
    mov $1,%ebx
    mov %esp,%ecx
    mov $3,%edx
    int $0x80

    mov $1,%eax
    int $0x80

What I would expect this program to do is push 0, 10, and 65 to the stack so that the stack is 65, 10, 0 (capital A, new-line, end of string). Set eax and ebx to the values for writing to stdout, and setting ecx to the stack pointer so that it writes what's on the stack, while edx is the length of what's on the stack(i.e. 3). When I run this, absolutely nothing happens. Can you help me understand what I'm doing wrong and what is actually happening here?


Solution

  • Each push instruction pushes 4 bytes onto the stack. So, this is how the stack looks like before the int 0x80:

       ....
    ----------  (highest address)
    |  0x00  |
    ---------- 
    |  0x00  |
    ---------- 
    |  0x00  |
    ---------- 
    |  0x00  |
    ---------- <-- push $0
    |  0x00  |
    ---------- 
    |  0x00  |
    ---------- 
    |  0x00  |
    ---------- 
    |  0x0A  | 
    ---------- <-- push $10
    |  0x00  |
    ---------- 
    |  0x00  |
    ---------- 
    |  0x00  |
    ---------- 
    |  0x41  |
    ---------- <-- push $65 <-- ESP
    

    However, at that moment you would like the stack to look like:

       ....
    ---------- 
    |  0x00  |
    ---------- 
    |  0x0A  |
    ---------- 
    |  0x41  |
    ---------- <-- ESP
    

    This can be achieved by replacing your push instructions by the following:

    push $0x0a41
    

    That is:

    .text
    .global main
    main:
        push $0x0a41
    
        mov $4,%eax    ;system call write()
        mov $1,%ebx    ;file descriptor (stdout)
        mov %esp,%ecx  ;string
        mov $3,%edx    ;length of the string
        int $0x80
    
        mov $1,%eax
        int $0x80
    

    In the edx register you are already specifying the length of the string (i.e.: 3), the NUL character is pointless (you are actually sending it to stdout).