Author Topic: Help with writing custom C type string functions using NASM  (Read 48013 times)

Offline turtle13

  • Jr. Member
  • *
  • Posts: 73
Re: Help with writing custom C type string functions using NASM
« Reply #45 on: September 10, 2017, 02:56:06 AM »
completed l_puts:

Code: [Select]
bits 32

section .text

global l_puts

l_puts:
        push ebp                ; prologue
        mov ebp, esp   

        push ebx                ; preserve ebx
        push edi                ; preserve edi
        push esi                ; preserve esi

        mov ebx, 1              ; 1= stdout     
        mov ecx, [ebp + 8]      ; const char *buf [address of string] goes into ecx (first and only parameter)
       
        xor edx, edx            ; set up a counter

        .char_loop:
                cmp [ecx + edx], byte 0         ; look for null terminator
                je .found_len
               
                inc edx                 ; counter + 1
                jmp .char_loop



                inc edx
                jmp .char_loop

        .found_len:
                mov eax, 4              ; sys write
                int 0x80

                test eax, eax           ; set flags
                jns .done               ; jump if zero or positive (no error)
                mov eax, -1             ; set error code if error


        .done:
                pop esi                 ; restore esi
                pop edi                 ; restore edi               
                pop ebx                 ; restore ebx

                mov esp, ebp            ; epilogue
                pop ebp
                ret

Offline turtle13

  • Jr. Member
  • *
  • Posts: 73
Re: Help with writing custom C type string functions using NASM
« Reply #46 on: September 10, 2017, 03:04:31 AM »
completed l_open:

Code: [Select]
bits 32

section .text

global l_open

l_open:
        push ebp                ; prologue
        mov ebp, esp

        push ebx                ; preserve registers
        push edi
        push esi

        mov ebx, [ebp + 8]      ; name of the file (const char * name)
        mov ecx, [ebp + 12]     ; flags
        mov edx, [ebp + 16]     ; mode

        mov eax, 5              ; open sys call
        int 0x80

        cmp eax, 0              ; check for error
        jl .error

        .done:
                pop esi         ; restore registers
                pop edi
                pop ebx

                mov esp, ebp    ; epilogue
                pop ebp
                ret

        .error:
                mov eax, -1
                jmp .done

int l_open(const char *name, int flags, int mode)
opens the named file with the supplied flags and mode. Returns the integer file descriptor of the newly opened file or -1 if the file can't be opened.

Offline turtle13

  • Jr. Member
  • *
  • Posts: 73
Re: Help with writing custom C type string functions using NASM
« Reply #47 on: September 10, 2017, 03:19:27 AM »
completed l_close:

Code: [Select]
bits 32

section .text

global l_close

l_close:
        push ebp                ; prologue
        mov ebp, esp

        push ebx                ; preserve registers
        push edi
        push esi

        mov ebx, [ebp + 8]      ; file descriptor

        mov eax, 6              ; close sys call
        int 0x80

        cmp eax, 0
        jl .error               ; check for error
        je .success             ; check for success

        .done:
                pop esi         ; restore registers
                pop edi
                pop ebx

                mov esp, ebp    ; epilogue
                pop ebp
                ret       

        .error:
                mov eax, -1
                jmp .done
        .success:
                mov eax, 0
                jmp .done

int l_close(int fd)
close the indicated file, returns 0 on success or -1 on failure.

Offline turtle13

  • Jr. Member
  • *
  • Posts: 73
Re: Help with writing custom C type string functions using NASM
« Reply #48 on: September 10, 2017, 03:57:30 AM »
And finally, the last function, "l_exit"

Code: [Select]
bits 32

section .text

l_exit:

; are these needed for exit:
;        push ebp                ; prologue
;        mov ebp, esp

;        push ebx                ; preserve registers
;        push edi
;        push esi

        mov ebx, [ebp + 8]      ; int rc
       
        mov eax, 1              ; exit sys call
        int 0x80

int l_exit(int rc)
terminate the calling program with exit code rc.

Offline turtle13

  • Jr. Member
  • *
  • Posts: 73
Re: Help with writing custom C type string functions using NASM
« Reply #49 on: September 10, 2017, 04:03:38 AM »
Should I be performing xor on all of these registers at the beginning of all of these functions?

Offline turtle13

  • Jr. Member
  • *
  • Posts: 73
Re: Help with writing custom C type string functions using NASM
« Reply #50 on: September 10, 2017, 04:21:18 AM »
Your l_gets seems to work great! However, it looks like it is repeating the same line 7 times, care to extrapolate on that one?
The return value 37 is correct, 36 characters + linefeed  :D



*edit aha, never mind, I see in the testmain code that you are repeating 7 times (esi= 7)
Ignore this post!

This is what I've got for l_gets. It's pretty much your code. I moved "inc esi" up to the top so our first try is 1, not 0. If esi==len, we do want to do that read, in case the LF is there. Now we do. I cut back to reading one byte at a time, little as I like it. Fugly! I did not attempt to "flush the buffer". I indicated where we might want to - only if we're reading from stdin!

Code: [Select]
; nasm -f elf32 l_gets.asm -d TESTMAIN
; ld -o l_gets l_gets.o

bits 32

%ifdef TESTMAIN

section .bss
buf resb 80
fd resd 1

section .data
filename db `l_gets.asm\0` ; ourself - we know it's there

section .text
global _start
_start:

mov eax, 5 ; sys_open
mov ebx, filename
xor ecx, ecx
xor edx, edx
int 80h
test eax, eax
js exit ; bail out if error
mov [fd], eax

; test a call to it

; try multiple calls if we're reading file
; just to make sure we're stopping at LF
; and can continue from there
mov esi, 7
top:

push 80 ; length
push buf
push dword [fd]
call l_gets
add esp, 4 * 3

; print what we l_getsed - l_got?

mov edx, eax ; length read
mov eax, 4  ;sys_write
mov ebx, 1 ; stdout
mov ecx, buf
int 80h

; only if we're doing multiple reads
dec esi
jnz top

exit:
                mov ebx, eax            ; return value is number of bytes written (len)
                mov eax, 1              ; sys exit
                int 0x80
%endif
;-----------------------------
section .text

global l_gets

l_gets:
        push ebp                ; prologue
        mov ebp, esp

        push ebx                ; preserve ebx
push esi

        mov ebx, [ebp + 8]      ; fd parameter into ebx
        mov ecx, [ebp + 12]     ; char *buf in ecx
        mov edx, [ebp + 16]     ; len in edx
        xor esi, esi            ; counter

        cmp edx, 0              ; if len zero or less, exit
        jle .done

mov edx, 1 ; read one byte at a time. ugh!

        .char_loop:       
        inc esi ; increment count first
                mov eax, 3              ; sys read
                int 0x80

                cmp [ecx], byte 0xA     ; test for linefeed
                je .done

                inc ecx                 ; advance to next byte

                cmp esi, [ebp + 16]     ; does read bytes = len?
                je .done
; if this happens, we didn't find a LF
; if we're reading stdin, this indicates overflow
; we might want to flush OS's input buffer ("keyboard buffer")

                jmp .char_loop
       
        .done:
                mov eax, esi            ; # bytes read into eax               

        pop esi
        pop ebx                 ; restore ebx

                mov esp, ebp            ; epilogue
                pop ebp
                ret
;-----------------------------------------------


That's as far as I got. I'm not sure it's "complete". See what you think...

Best,
Frank

Ah, again we're bumping into each other. Your l_write looks good at first glance. It returns the number of bytes written because that's what sys_write does!

Offline turtle13

  • Jr. Member
  • *
  • Posts: 73
Re: Help with writing custom C type string functions using NASM
« Reply #51 on: September 15, 2017, 12:50:01 AM »
In regards to l_open not working here are feedback comments:

Your l_open doesn't work correctly.  After sys_open, you don't check the return value.  Your l_open should return -1 if you fail to open the file for any reason.

My l_open code:

Code: [Select]
l_open:

        push ebp                ; prologue
        mov ebp, esp

        push ebx                ; preserve registers
        push edi
        push esi

        mov ebx, [ebp + 8]      ; name of the file (const char * name)
        mov ecx, [ebp + 12]     ; flags
        mov edx, [ebp + 16]     ; mode

        mov eax, 5              ; open sys call
        int 0x80

        cmp eax, 0              ; check for error
        jl .error

        .done:
                pop esi         ; restore registers
                pop edi
                pop ebx

                mov esp, ebp    ; epilogue
                pop ebp
                ret

        .error:
                mov eax, -1
                jmp .done


So.. how to fix so that it returns -1 for failure to open?

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Help with writing custom C type string functions using NASM
« Reply #52 on: September 15, 2017, 01:59:45 AM »
That looks correct to me!