1

I decided to make a function that prints a string in the EAX register to the console, works from a part by displaying a message first, then something

Code (NASM) :

newLine equ 0xa

section .data
    msg db "Hello world!", newLine, 0

section .text
    global _start

_start:
    mov eax, msg
    call printf
    call exit

printf:
    push eax
    push ebx
    push ecx 
    push edx 

    mov ecx, eax
    call lenFind
    mov edx, eax
    mov eax, 4
    mov ebx, 1
    int 0x80

    pop edx
    pop ecx
    pop ebx
    pop eax 
    ret

lenFind:
    push edx
    mov edx, 0
    .find:
        cmp [eax+edx], byte 0
        je .close
        inc edx
        jmp .find
    .close:
        pop edx
        ret

exit:
    mov eax, 1
    mov ebx, 0
    int 80h 

Output:

Hello world!
.shstrtab.text.data
                   �J�  

idk what it could be, but most likely the problem is that I'm using 32 bit registers

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • It looks like your call to `lenFind` expects that it will return the string's length in `eax`. But if you read what you wrote in `lenFind`, it doesn't. It doesn't modify `eax` at all, so it still contains the pointer to `msg` when it returns. It would have the correct length in `edx` when the loop exits, but you discard that value with `pop edx` instead of doing anything useful with it. I think you want a `mov eax, edx` just before the `pop edx`. – Nate Eldredge Mar 20 '22 at 15:28
  • Looks like all that saving and restoring or registers is mostly making things harder. Normal calling conventions allow functions to trash ECX and EDX without saving/restoring. (As well as EAX if it's not a return value). These are called ["call clobbered" registers, as opposed to "call preserved"](https://stackoverflow.com/questions/9268586/what-are-callee-and-caller-saved-registers/56178078#56178078). – Peter Cordes Mar 20 '22 at 15:41

1 Answers1

3

Your lenFind does not return any result!
The length is calculated in the EDX register but you have restored that from the stack. However the calling program seems to expect the length to be in the EAX register:

lenFind:
    push edx
    mov edx, 0
    .find:
        cmp [eax+edx], byte 0
        je .close
        inc edx
        jmp .find
    .close:
        MOV EAX, EDX   <<< Add this line
        pop edx
        ret
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • It does return a result, the original EAX. Which is a pointer, thus a large integer. Thus the whole rest of the page (or contiguous range of page mappings) gets written to stdout, because Linux `write` doesn't check later page permissions before starting to copy readable data to the fd. You only get `-EFAULT` if the first page is unreadable, even with a huge size that extends into unmapped pages. – Peter Cordes Mar 20 '22 at 15:32