NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: RogerRabbit on May 07, 2011, 07:20:49 AM
-
Hi there, I'm using YASM (which I understand to be very similar to NASM) and I was wondering if you could help me. I'm trying to write a bit of code to use bubblesort to sort a 10 character string. Here's what I've got:
arrSize equ 10
section .bss ; unititialised data
iobuf resb 1 ; used by putChar
strbuf resb arrSize
section .data ; initialized data and constants
msg db 'Enter 10 Digits: '
len equ $ - msg
msg1 db 'Sorted: '
len1 equ $ - msg1
section .text ; instructions
global _start
_start:
mov edx, len
mov ecx, msg
call putString ;print message
mov esi, '0' ;pointer
mov edi, strbuf ;base add of array
reading:
call getChar
mov [edi+1*esi], al ; store it
inc esi
cmp esi, arrSize
jl reading
mov al, 0x0A ; newline
call putChar
mov edx, len1
mov ecx, msg1
call putString
mov esi, '0' ; index = 0
mov edi, [arrSize] ; index = 0
sorting: ;edi is sorting loop index
innerLoop:
swap:
mov eax, [edi+1*esi]
cmp eax, [edi+2*esi]
jl swapend
mov eax, [edi+1*esi]
mov ebx, [edi+2*esi]
mov [edi+1*esi], ebx
mov [edi+2*esi], eax
swapend:
cmp esi, edi
jl innerLoop;
dec edi
cmp edi, 1 ;loop
jg sorting
writing:
mov al, [edi+1*esi] ; i'th byte of str
call putchar
dec esi
cmp esi, 0
jge writing
mov al, 0x0A ; newline
call putchar
mov eax, 1 ; exit()
int 0x80 ; make the system call
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
putChar: ; write a char to stdout
mov [iobuf], al ; load iobuf with al
mov edx, 1
mov ecx, iobuf
mov ebx, 1
mov eax, 4
int 0x80
mov al, [iobuf] ; restore char in al
ret
getChar: ; read a char from stdin
rawmode
mov edx, 1
mov ecx, iobuf
mov ebx, 0
mov eax, 3
int 0x80
normalmode
mov al, [iobuf] ; load al
ret
putString: ; ecx has address, edx has length
mov ebx, 1
mov eax, 4
int 0x80
ret
I'm running into a few issues. When I run, i get a segmentation fault as follows:
roger@assm -$ ./sort
Enter 10 Digits: 1234567890
Segmentation fault
roger@assm -$ 234567890
234567890: command not found
/code]
-
mov edi, [arrSize] ; index = 0
There's your segfault. "arrSize" = 10, so you're trying to read the contents of memory location 10 - which is outside your process's memory. Just "mov edi, arrSize", no brackets.
The "234567890" on the command line suggests that "getchar" isn't working as intended. What are "rawmode" and "normalmode"? I'll have to look at this some more...
Best,
Frank
-
As you've probably discovered, that still segfaults...
mov esi, '0' ; index = 0
mov edi, [arrSize] ; index = 0
sorting: ;edi is sorting loop index
innerLoop:
swap:
mov eax, [edi+1*esi]
cmp eax, [edi+2*esi]
jl swapend
mov eax, [edi+1*esi]
mov ebx, [edi+2*esi]
mov [edi+1*esi], ebx
mov [edi+2*esi], eax
swapend:
cmp esi, edi
jl innerLoop;
You make esi '0' (30h or 48 decimal) and edi... well, "arrsize" maybe. [esi + edi] is still going to be outside your process' memory. You need to get "strbuf" in there somehow! Probably in one of those registers. Then, you want to load, compare, and maybe swap bytes (right?) but you're using 32-bit registers, which will load and compare dwords. You probably want to use al and bl there - or maybe al and ah, leave ebx alone? Still 32-bit registers for addressing memory, of course. When you get to the end, you compare edi with esi - you haven't changed either, so you're going to "jl" always or never. You probably don't want "2*esi" there, but [edi + esi +1] - to compare (and swap?) the "next" byte to the one you're examining. That whole section needs re-writing. (and some of the remainder, too, but most of it's pretty good)
I still don't know what "rawmode" and "normalmode" are... Well, I think I can guess what they're supposed to do... sys_read doesn't return after reading just the one character(!). It only puts one character in your buffer, but it doesn't return until you hit "enter". Remaining characters that were typed stay in the "OS's buffer" - available for the next sys_read, which will end up on the command line, if it doesn't get read within your program. If you can keep it from segfaulting, and if the pesky user enters only ten "digits", this may not be a problem. There's a way - using sys_ioctl, I think - to make a read on STDIN return "just one key, please", so you don't have to prompt "Hit any key as long as it's 'Enter' to continue"... Have you got some macros for that, or something?
Best,
Frank