I am writing a little divisibility program in nasm for learning purposes but I keep getting the "floating point exception" whenever I try running it. Here is the code:
segment .data
x dw 7
y dw 2
segment .bss
num resb 2
segment .text
global _start
_start:
mov cx, 1
mov bx, 0
label1:
mov ax, cx
xor bx, bx
xor edx, edx
mov bx, word [x]
div bx
cmp edx, 0
jne next
mov ax, cx
xor bx, bx
xor edx, edx
mov bx, word [y]
div dx
cmp edx, 0
jne next
mov [num], cx
mov eax, 4
mov ebx, 1
mov ecx, num
mov edx, 2
int 80h
add bx, 1
next:
add cx, 1
cmp cx, 100
jle label1
exit:
mov eax, 1
xor ebx, ebx
int 80h
I would appreciate if someone could point out what I am doing wrong!
You've got this line in your code:
div dx
Obviously dividing by dx is a bad idea since dx also is part of the dividend, and you've correctly set dx to zero prior to the division. I assume that this is a typo and that you really meant to write
div bx
Related
and thanks for taking the time.
With some help from stackoverflow and my professor, i managed to write a procedure that draws a 32 by 32 image to the window, using masm assembly and a library called canvas.lib.
However, back home i realized that when i call it twice it crashes my little game.
Here is the procedure definition.
drawimage proc
push ebp
mov ebp, esp
sub esp, 12
pusha
mov ecx, 0
outerloop:
cmp ecx, sprite_height
je done
mov ebx, 0
innerloop:
mov [ebp-8], ecx
mov [ebp-12], ebx
pusha
mov eax, [ebp-8]
mov ebx, sprite_width
mul ebx
add eax, [ebp-12]
shl eax, 2
mov esi, [ebp+8]
add esi, eax
push [esi]
pop [ebp-4]
mov eax, [ebp+20]
add eax, [ebp-8]
mov ebx, area_width
mul ebx
add eax, [ebp-12]
add eax, [ebp+16]
shl eax, 2
mov esi, [ebp+12]
add esi, eax
mov eax, [ebp-4]
mov dword ptr [esi], eax
popa
cmp ebx, sprite_height
je innerloopdone
inc ebx
jmp innerloop
innerloopdone:
inc ecx
jmp outerloop
done:
popa
mov esp, ebp
pop ebp
ret 12
drawimage endp
The function definition would look like this in c
void drawimage(int* image, int* windowmatrix, int x, int y);
I am calling the function here twice and the program crashes.
draw proc
push ebp
mov ebp, esp
push 240
push 320
push area
push offset bomb
call drawimage
add esp, 16
push 32
push 32
push area
push offset bomb
call drawimage
add esp, 16
mov esp, ebp
pop ebp
ret
draw endp
Bomb is a 32 x 32 matrix of 32 bit pixels, and area is a pointer to an allocated memory of 640 x 480 pixels. The memory used for area is allocated with malloc, so the value stored in area is in fact a pointer.
My guess is there is something i am not reverting back to normal in the function, but i still can't see why calling the function only once works normally. Any ideas?
I'm using the Irvine32.inc library, and am having an issue with my L4 jump.
L1:
mov edx, offset optionPromptMsg
call WriteString
call ReadInt
mov ebx, 1
cmp eax, ebx
je L2 //if eax is 1, jump to l2, if eax is -1, jump l3
mov ebx, -1
cmp eax, ebx
je L3
mov ebx, -2
mov ecx, 2
cmp ebx, eax //if eax is less than -2 or more than 2 jump to L4
ja L4
cmp eax, ecx
ja L4
L2: call NextScore
L4: mov edx, offset optionErrorMsg
call WriteString
loop L1
L3 : call WriteScore
No matter how I format it, for some reason everytime L2: call NextScore is called, immediantly afterward L4 is called and I can't figure out why. NextScore is as follows...
NextScore PROC USES esi
mov edx, offset scorePromptMsg
call WriteString
call ReadInt
mov ebx, 0
mov ecx, 100
cmp ebx, eax
ja L1
cmp eax,ecx
ja L1
jmp L2
L1:
mov edx, offset scoreErrorMsg
call WriteString
L2:
mov scores[esi*4], eax
inc esi
ret
NextScore ENDP
As you see, NextScore reads in a value from 0-100 then, unsuccessfully at this time, adds that value to an array scores. For some reason it only adds duplicates of one number throughout the entire array,but that's an entirely different issue. Any thoughts or ideas are most appreciated!
The ret at the end of NextScore goes back exactly to L4 because every ret goes back to continue where the matching call left off. That is if you want to do something else, you need to add code before L4 that gets executed when NextScore returns (such as a jmp to wherever you want to go instead of L4):
I'm trying to make an x86 function that accepts two strings as arguments and determines which is larger. The arguments are obtained through user input and I'm using NASM. However once I get this to work I'm just going to call my assembly function in a c program so this might just be giving myself more work than needed for testing. I'd really appreciate any help finding out why this code seg faults.
SECTION .data
greet: db "Type a word: "
greetL: equ $-greet
bigprompt: db "First is bigger"
bigpromptL: equ $-bigprompt
smallprompt: db "Second is bigger"
smallpromptL: equ $-smallprompt
sameprompt: db "They same: "
samepromptL: equ $-sameprompt
LF: equ 10
SECTION .bss
first: resb 30
second: resb 30
SECTION .text
global _start
_start:
nop
mov eax, 4 ; ask for first word
mov ebx, 1
mov ecx, greet
mov edx, greetL
int 80H
mov eax, 3 ; get first word
mov ebx, 0
mov ecx, first
mov edx, 30
int 80H
mov eax, 4 ; ask for second word
mov ebx, 1
mov ecx, greet
mov edx, greetL
int 80H
mov eax, 3 ; get second word
mov ebx, 0
mov ecx, second
mov edx, 30
int 80H
push first
push second
call _Stringgt
mov esi, eax
jmp DONE
_Stringgt:
push ebp
mov ebp, esp
push edx
mov eax, [ebp+8]
mov ebx, [ebp+12]
cld
xor ecx, ecx
LOOP:
mov al, [eax + ecx]
cmp [ebx + ecx], al
jb BIGGER
ja SMALLER
cmp al, LF
je SAME
inc ecx
jmp LOOP
BACK:
pop ebp
ret
BIGGER:
mov eax, bigprompt
jmp BACK
SMALLER:
mov eax, smallprompt
jmp BACK
SAME:
mov eax, sameprompt
jmp BACK
DONE:
mov eax, 4
mov ebx, 1
mov ecx, esi
mov edx, 30
int 80H
mov eax, 1 ; exit
mov ebx, 0
int 80H
This is too simple. you can use this function to get lengths of strings and determine which is larger.
;---------------------------------------------------------
;IN: takes zero terminated string address as parameter on stack
;OUT: String length in AX
;---------------------------------------------------------
str_length:
mov bp,sp
mov si, [bp+2]
mov al, [si]
mov bx,0
.loop:
cmp byte [si], 0
je .done
add si,1
add bx,1
jmp .loop
.done:
mov ax,bx
ret
;--------------------------------------------------------------
Now you can do str_length two times and compare string lengths, such as
main:
mov ax,string1
push ax ;give function parameter
call str_length ;call the function
mov dx,ax ;store string length in dx
mov ax,string2
push ax
call str_length ; do this for string2
;now length of string1 is in dx and string2 is in ax we can compare them
cmp ax,dx
je equal
cmp ax,dx
ja greater
cmp ax,dx
jl less
This is what I have so far, it will display the fraction but nothing else:
INCLUDELIB c:\masm32\lib\user32.lib
INCLUDELIB c:\masm32\lib\kernel32.lib
.data
str1 BYTE "Enter the numerator: ",0
str2 BYTE "Enter the denominator: ",0
str3 BYTE "/",0
str4 BYTE "The fraction you entered is: ",0
str5 BYTE "Simplest form of your fraction: ",0 ;msg9
str6 BYTE "You can't store a 0 in the denominator",0dh, 0ah, 0
str7 BYTE " ",0dh, 0ah, 0
num1 SDWORD 0 ;n1
num2 SDWORD 0 ;n2
tempN SDWORD 0
tempD SDWORD 0
temp3 SDWORD 0
tempR SDWORD 0
.code
main PROC
call Clrscr
mov eax,0
mov ebx,0
mov ecx,0
call fractionPrompt
call gcd
call displayFraction
exit
main ENDP
fractionPrompt PROC
mov edx, OFFSET str1 ;prompt for numerator
J1:
call writestring
call readDec
mov num1,eax
jmp J2
J2:
mov edx,OFFSET str2 ;Prompt for denominator
call writestring
call readDec
mov num2,eax
cmp eax,0
je reenter
jne OP1
reenter:
mov edx,OFFSET str7
call writestring
mov edx,OFFSET str6
call writestring
OP1:
mov edx, OFFSET str7
call writestring
mov edx,OFFSET str4
call writestring
mov eax,num1
call writeDec
mov tempN,eax
mov edx, OFFSET str3
call writestring ;/
mov eax,num2
mov tempD,eax
call writeDec
ret
fractionPrompt ENDP
gcd PROC
mov eax,tempN
cdq
mov ebx,tempD
mov edx,0
div ebx
cmp edx,0
jne J1
je J2
J1:
mov eax,tempD
mov edx,0
dec temp3
div temp3
mov temp3,edx
cmp edx,0
je J2
loop J1
J2:
mov eax,tempN
neg eax
cdq
mov edx,0
div temp3
cmp edx,0
je J3
dec temp3
loop J2
J3:
mov eax,tempN
cdq
div temp3
mov tempN,eax
call writeDec
mov eax,tempD
cdq
div temp3
mov tempD,eax
call writeDec
ret
gcd ENDP
displayFraction PROC
mov edx,OFFSET str5
call writestring
mov tempN,eax
call writeDec
mov edx, OFFSET str3
call writestring
mov ebx,tempD
call writeDec
ret
displayFraction ENDP
END main
Your code is so erroneous that it isn't worth to correct it, respectively, I tried and failed. Take a look at this working example (Masm32 Version 11):
include \masm32\include\masm32rt.inc
.data
num SDWORD 15 ; example numerator
denom SDWORD 12 ; example denominator
gcd SDWORD 0
.code
get_gcd PROC arg1:DWORD, arg2:DWORD
mov eax, arg1
mov ecx, arg2
test ecx, ecx
jz _Ret
##:
cdq
idiv ecx
test edx, edx
jz _Ret
mov eax, ecx
mov ecx, edx
jmp #B
_Ret:
mov eax, ecx
cdq ; EAX = abs(EAX)
add eax, edx
xor eax, edx
ret
get_gcd ENDP
main PROC
printf ("Fraction: %i / %i\n",num,denom)
invoke get_gcd, num, denom
mov gcd, eax
printf ("GCD: %i\n",eax)
mov eax, num
cdq
idiv [gcd]
mov num, eax
mov eax, denom
cdq
idiv [gcd]
mov denom, eax
printf ("Reduced: %i / %i\n",num,denom)
invoke ExitProcess, 0
main ENDP
END main
I have this disassembled function:
PUSH EBP
MOV EBP, ESP
SUB ESP, C
PUSH 408506
MOV EAX, DWORD PTR FS:[0]
PUSH EAX
MOV DWORD PTR FS:[0], ESP
SUB ESP, 14
PUSH EBX
PUSH ESI
PUSH EDI
MOV DWORD PTR [EBP-C], ESP
MOV DWORD PTR [EBP-8], 4077D8
XOR EBX, EBX
MOV DWORD PTR [EBP-4], EBX
MOV EDI, DWORD PTR [EBP+8]
PUSH EDI
MOV EAX, DWORD PTR [EDI]
CALL NEAR DWORD PTR [EAX+4]
MOV ESI, DWORD PTR [EBP+C]
MOV ECX, DWORD PTR [EDI]
LEA EDX, DWORD PTR [EBP-1C]
MOV DWORD PTR [EBP-18], EBX
PUSH EDX
PUSH ESI
PUSH EDI
MOV DWORD PTR [EBP-1C], EBX
CALL NEAR DWORD PTR [ECX+37C]
CMP WORD PTR [EBP-1C], BX
JE 00558206
MOV EAX, DWORD PTR [EDI+D8]
CMP EAX, EBX
JE 0055819A
CMP WORD PTR [EAX], 1
JNZ 0055819A
MOV EDX, DWORD PTR [EAX+14]
MOV ECX, DWORD PTR [EAX+10]
MOV EBX, DWORD PTR [401190]
MOVSX ESI, SI
SUB ESI, EDX
CMP ESI, ECX
JB 0055818F
CALL NEAR EBX
LEA EAX, DWORD PTR [ESI+ESI*4]
LEA EAX, DWORD PTR [EAX+EAX*4]
SHL EAX, 5
JMP 005581A2
MOV EBX, DWORD PTR [401190]
CALL NEAR EBX
MOV ECX, DWORD PTR [EDI+D8]
MOV EDX, DWORD PTR [ECX+C]
MOV ECX, DWORD PTR [EBP+10]
MOV AX, WORD PTR [EDX+EAX+2C8]
MOV WORD PTR [ECX], AX
MOV EAX, DWORD PTR [EDI+D8]
TEST EAX, EAX
JE 005581E6
CMP WORD PTR [EAX], 1
JNZ 005581E6
MOVSX ESI, WORD PTR [EBP+C]
MOV EDX, DWORD PTR [EAX+14]
MOV ECX, DWORD PTR [EAX+10]
SUB ESI, EDX
CMP ESI, ECX
JB 005581DB
CALL NEAR EBX
LEA EAX, DWORD PTR [ESI+ESI*4]
LEA EAX, DWORD PTR [EAX+EAX*4]
SHL EAX, 5
JMP 005581E8
CALL NEAR EBX
MOV EDX, DWORD PTR [EDI+D8]
MOV DWORD PTR [EBP-18], -1
MOV ECX, DWORD PTR [EDX+C]
MOV DX, WORD PTR [ECX+EAX+2CA]
MOV EAX, DWORD PTR [EBP+14]
MOV WORD PTR [EAX], DX
MOV EAX, DWORD PTR [EBP+8]
PUSH EAX
MOV ECX, DWORD PTR [EAX]
CALL NEAR DWORD PTR [ECX+8]
MOV EDX, DWORD PTR [EBP+18]
MOV AX, WORD PTR [EBP-18]
MOV WORD PTR [EDX], AX
MOV EAX, DWORD PTR [EBP-4]
MOV ECX, DWORD PTR [EBP-14]
POP EDI
POP ESI
MOV DWORD PTR FS:[0], ECX
POP EBX
MOV ESP, EBP
POP EBP
RETN 14
I can guess that the function takes maybe 5 arguments of 4 bytes each one because of the RETN 14(0x14 = 20 right?). Then I can also see in that disassembled code things like EBP+8 and EBP+C so I think "Oh, those are the first and second arguments". Well, right, those are the first and second arguments of the function. But I can't guess where are the other ones. I tried EBP+16, EBP+20 and EBP+24 but the values that they give me doesn't sound like the arguments.
How can I interpretate this disassembled code?
Thanks in advance.
Your assumption is right; scanning through the disassembly, I found five parameters being referenced, all DWORD so 4 bytes each:
DWORD PTR [EBP+8] ; first parameter (the first 8 bytes are reserved for return address and original EBP)
DWORD PTR [EBP+C] ; hexadecimal C = decimal 12
DWORD PTR [EBP+10] ; hexadecimal 10 = decimal 16
DWORD PTR [EBP+14] ; hexadecimal 14 = decimal 20
DWORD PTR [EBP+18] ; hexadecimal 18 = decimal 24
Considering the numbers you proposed for parameters 3/4/5, I suppose you just got confused when converting between decimal and hexadecimal; you should keep a table of numbers by your side until this has become second nature to you.
EDIT: about calling convention...
The disassembly appears to be a function with stdcall calling convention. To call the function, you first have to push each double-word parameter value on the stack, from right to left (i.e. the first parameter is the last one to push). The function cleans up the stack, so you don't have to pop anything afterwards. You can find source samples here:
http://www.unixwiz.net/techtips/win32-callconv.html
http://pic.dhe.ibm.com/infocenter/ratdevz/v7r5/index.jsp?topic=%2Fcom.ibm.etools.pl1.win.doc%2Ftopics%2Fxf6854-z.htm