简体   繁体   中英

x86 asm printf causes segfault when using intel syntax (gcc)

I'm just starting to learn x86 assembly, and I am a bit confused as to why this little example doesn't work. All I want to do is to print the content of the eax register as a decimal value. This is my code in AT&T Syntax:

.data
intout:
    .string "%d\n"
.text
.globl main

main:

movl $666, %eax
pushl %eax
pushl $intout
call printf

movl $1, %eax
int $0x80

Which I compile and run as follows:

gcc -m32 -o hello helloworld.S
./hello

This works as excepted (Printing 666 to the console). On a little side note, I would like to point out that I don't understand what exactly "movl $1, %eax" and "int $0x80" are supposed to accomplish here. I'm also a not sure what "pushl $intout" does. Why is my output composed out of two separate stack entries? And what exactly does the .string macro do?

These are only side questions however, since my real problem is that I can't find a way to make this run using the much easier to read/write/comprehend Intel syntax.

Here is the code:

.intel_syntax noprefix

.data
    intout:
        .string "%d\n"
.text
.globl main

main:

mov eax, 666
push eax
push intout
call printf

mov eax, 1
int 0x80

Running this same as above, it just prints "Segmentation fault".

What am I doing wrong?

You need to use push OFFSET intout otherwise the 32-bit value stored at intout will be pushed on the stack, rather than its address.

intout is just a label, which is basically a name assigned to an address in your program. The .string "%d\\n" directive that follows it defines a sequence of bytes in your program, both allocating memory and initializing that memory. Specifically it allocates 4 bytes in the .data section and initializes them with the characters '%' , 'd' , '\\n' , and '\\0' . Since the label intout is defined just before the .string line it has the address of the first byte in the string.

The line push intout results in a instruction that reads the 4 bytes starting at the address of referred to by intout and pushes them on to the stack (specifically it subtracts 4 from ESP and then copies them to the 4 bytes now pointed to by ESP.) The line push $intout (or push OFFSET intout ) pushes the 4 bytes that make up the 32-bit address of intout on the stack.

This means that the line push intout pushes a meaningless value on to the stack. The function printf ends up interpreting it as a pointer, an address where the format string is supposed to be stored, but since it doesn't point to valid location in memory your program crashes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM