Reputation: 167
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
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