0

Hi I'm new to x86 assembly and I wanted to try implementing a basic print function that takes the address of the string to be printed and its length that executes the write interrupt on it.

I did the following:

.global _start
.intel_syntax
.section .text    

# void print(char *msg, int len) 
print:
    push %bp
    mov %bp, %sp

    mov %ecx, [%bp+6]   # len
    mov %edx, [%bp+4]   # msg

    mov %eax, 4
    mov %ebx, 1
    int 0x80

    pop %bp
    ret 4

_start:
    push [msg]
    push 13
    call print      # print(msg, len)

    mov %eax, 1
    mov %ebx, 0
    int 0x80

.section .data
msg:
    .ascii "Hello, world!\n"

I compiled it with the following commands:

as test.asm --32 -o test.o 
gcc -m32 test.o -nostdlib

The resulting error is of course s Segfault but I don't understand where I'm going wrong.

Any advice?

Leon Gurin
  • 27
  • 1
  • 8
  • I'd highly recommend using either `.intel_syntax noprefix`, or the default (`.att_syntax`), not this mutant hybrid of Intel syntax with `%` decorations on register names. – Peter Cordes Sep 30 '22 at 10:50
  • `[bp+6]` uses 16-bit address-size, and so you're truncating the 32-bit stack pointer to 16-bit. (It's *guaranteed* to fault on a normal Linux system because [there won't be any valid addresses](https://wiki.debian.org/mmap_min_addr) in the low 64KiB of virtual address space.) Use a debugger to look at registers as you single-step. Also, `push` in `_start` is `pushl` (dword push) because this is 32-bit code, so the args aren't at those offsets, they're at 8 and 12 above EBP. – Peter Cordes Sep 30 '22 at 10:52
  • I assume you copied that code to access args from a 16-bit tutorial. That won't work, you should be using the same register width as the mode for addresses, so find a 32-bit tutorial. (Also, you want to pass the address of `msg`, not the first 4 bytes of ASCII data.) – Peter Cordes Sep 30 '22 at 11:15

0 Answers0