2

Here is an itoa implementation for macos 64 bits. Itoa requires strdup, which requires strlen, I'm posting these as well in case they're needed.

strlen:

section .text
    global  _ft_strlen

_ft_strlen:
    push    rbp
    mov     rbp, rsp

    push    rdi
    mov     rcx, -1
    xor     al, al
    cld
    repne   scasb

    not     rcx
    lea     rax, [rcx - 1]

    pop     rdi
    leave
    ret

strdup:

section .text
    global  _ft_strdup
    extern  _ft_strlen
    extern  _malloc

_ft_strdup:
    push    rbp
    mov     rbp, rsp

    push    rdi
    call    _ft_strlen
    inc     rax
    push    rax

    mov     rdi, rax
    call    _malloc

    test    rax, rax
    jz      .end

    pop     rcx
    pop     rsi
    mov     rdi, rax
    rep     movsb

.end:
    leave
    ret

itoa:

default rel

section .data
    buffer  times 11 db 0

section .text
    global  _ft_itoa
    extern  _ft_strdup

_ft_itoa:
    push    rbp
    mov     rbp, rsp

    xor     rcx, rcx                    ;initialize counter
    xor     r9, r9                      ;set neg flag to 0
    mov     eax, edi                    ;move number in RAX for DIV instruction
    push    rbx                         ;save RBX
    mov     ebx, 10

.check_negative:
    and     edi, 0x80000000
    lea     rdi, [buffer]
    jz      .divide                     ;number is positive, proceed to main loop
    not     eax                         ;else
    inc     eax                         ;compute absolute value with binary complement
    inc     r9                          ;set neg flag

.divide:
    xor     edx, edx
    div     ebx
    add     edx, 48                     ;convert int to char
    push    rdx
    inc     rcx
    cmp     eax, 0
    jnz     .divide

.check_neg_flag:
    cmp     r9, 1
    jne     .buff_string
    mov     byte[rdi], '-'

.buff_string:
    pop     rdx
    mov     byte[rdi + r9], dl
    dec     rcx
    inc     r9
    cmp     rcx, 0
    jnz     .buff_string
    pop     rbx                         ;IF THIS LINE IS SET, IT WORKS FINE

.dup:
    mov     byte[rdi + r9], 0
    call    _ft_strdup                  ;copy buffer string in memory and return pointer
    pop     rbx                         ;IF THIS LINE IS SET, SEGFAULT OCCURS

    leave
    ret

At the beginning of the function, I'm pushing RBX on the stack as I will be using it in the function. At the end of the function, my string is buffed, and I'm calling strdup to allocate a memory space and copy the string there. If I then pop RBX to clean the stack, the function segfaults. However, if I pop it just before calling strdup, everything works fine.

I do not use RBX in either strdup or strlen.

Why is this happening ?

Jon Nimrod
  • 335
  • 1
  • 2
  • 12
  • 3
    The issue is that the 64-bit System V ABI (that MacOS and Llinux uses) requires the stack be aligned on at least a 16-byte boundary (in some cases 32-byte, but doesn't apply here) before calling a function. If there isn't proper alignment before calling a _C_ library it may fault which is likely the case here. The push RBP aligns the stack to a 16-byte boundary. Pushing another value (RDI) misaligns the stack. – Michael Petch Jan 27 '19 at 18:55
  • 16-bits boundary you mean? – Jon Nimrod Jan 27 '19 at 19:18
  • 3
    No, 16 **bytes**. – Michael Petch Jan 27 '19 at 19:18

0 Answers0