Carlos Frank
Carlos Frank

Reputation: 167

assembly language modify input string error

I am trying to write a 32-bit x86 NASM program on Linux that takes in a string from a text file, encode shift all the characters in the string up by 1 and printf it out to the console. Pretty much everything works except the loop .rot132 which is use to do the shifting and printf. Whenever .rot132 is called it gives a segmentation_fault(core dump). I guess when I do mov ecx, [eax] it cause some kind of error. How can I overcome this part ?

;;sddddddddddddddddgsd

[SECTION .data] ; Section containing initialized data

WriteCode db "w",0
OpenCode db "r",0
Filename db "text.txt",0
fileFmt: dd "%c\n",10,0
fileFmt1: dd "%s",10,0

[SECTION .bss] ; Section containing uninitialized data
TextLenght EQU 72 ; Define length of a line of  text data
Text resb TextLenght ; Reserve space for disk-based help text line
BUFSIZE EQU 64 ; Define length of text line buffer 
Buff resb BUFSIZE+5 ; Reserve space for a line of text

[SECTION .text] ; Section containing code
;; These externals are all from the glibc standard C library:
extern fopen
extern fclose
extern fgets
extern fprintf
extern printf
extern sscanf
extern time

global main ; Required so linker can find entry point

main:

diskhelp:
        mov  ebx, Filename ; push file name to ebx
        push OpenCode ; Push pointer to open-for-read code “r“
        push ebx ; Pointer to name of help file is passed in ebx
        call fopen ; Attempt to open the file for reading
        add esp,8 ; Clean up the stack
        cmp eax,0 ; fopen returns null if attempted open failed
        jne .disk ; Read help info from disk file...
        ret

.disk:  mov ebx,eax ; Save handle of opened file in ebx

.rdln:  push ebx ; Push file handle on the stack
        push dword TextLenght ; Limit line length of text read
        push Text ; Push address of text line buffer
        call fgets ; Read a line of text from the file
        add esp,12 ; Clean up the stack
        ;cmp eax,0 ; A returned null indicates error or EOF
        ;jle .rot13 ; If we get 0 in eax, close up & return

        ;push Text ; Push address of help line on the stack
        ;call printf ; Call printf to display help line
        ;add esp,4 ; Clean up the stack

.rot131: ; initial shift and test, this work
        mov edx, 0    ; our counter
        mov eax, Text ; move string into eax
        mov ecx, [eax]; move first char in string into ecx
        add ecx, 1    ; shift the char up by 1 
        push ecx      ; push to print
        push fileFmt
        call printf
        add esp, 8   ; clear the stack
        inc edx      ; increase the counter

.rot132: 
        inc eax     ; shift address of eax into next char
        mov ecx, [eax] ; move the char into ecx, replace old char; error ??
        add ecx, 1     ; shift the char by 1
        push ecx        ; print
        push fileFmt
        call printf
        add esp, 8      ; clear the stack
        inc edx         ;incrase counter
        cmp edx,4       ; stop loop after edx = 4 
        jne .rot132


        push ebx ; Push the handle of the file to be closed
        call fclose ; Closes the file whose handle is on the stack
        add esp,4 ; Clean up the stack

        ret ; Go home

gdb debug : disassemble .rot132:

   0x08048559 <+0>:     inc    %eax
   0x0804855a <+1>:     mov    (%eax),%ecx
   0x0804855c <+3>:     add    $0x1,%ecx
   0x0804855f <+6>:     push   %ecx
   0x08048560 <+7>:     push   $0x804a035
   0x08048565 <+12>:    call   0x80483b0 <printf@plt>
   0x0804856a <+17>:    add    $0x8,%esp
   0x0804856d <+20>:    inc    %edx
   0x0804856e <+21>:    cmp    $0x4,%edx
   0x08048571 <+24>:    jne    0x8048559 <rot132>
   0x08048573 <+26>:    push   %ebx
   0x08048574 <+27>:    call   0x80483d0 <fclose@plt>
   0x08048579 <+32>:    add    $0x4,%esp
   0x0804857c <+35>:    ret
   0x0804857d <+36>:    xchg   %ax,%ax
   0x0804857f <+38>:    nop

Upvotes: 0

Views: 316

Answers (1)

doug65536
doug65536

Reputation: 6771

fileFmt needs to be db, not dd. You are defining doubleword characters.

Note that this code is not as good as compiler generated code. Only bother with assembly language for critical loops that are the obvious CPU bottleneck at the top of the profile, and you are already using a good algorithm.

An example is a matrix multiply. It is embarassingly parallel, so it is often beneficial to force the compiler to use the most efficient means available to do the operation, such as using a vector extension, like SSE.

Compilers are so good that you usually write "assembly language" with intrinsics, such as SSE or AVX intrinsics, which allow the compiler to worry about data flow and register allocation, and allows you to focus on the instructions themselves.

Also note Michael Petch's good comment: calls are allowed to clobber eax, ecx, edx. You can trust they will preserve ebx, esi, edi, ebp, esp. This means you need to stop using ecx and edx for your variables and use something that is preserved, like ebx, edi, esi, ebp.

Upvotes: 1

Related Questions