I'm a newbie when it comes to FASM, and pretty new to ASM in general, but I'm trying to compare two strings stored in the "variables": user_input
and exit_cmd
:
At the moment, it assembles fine but when I enter anything in the prompt it crashes. Yes, my code is messy and the task I'm trying to accomplish may seem out of my reach for the level of ASM I know, but I've done it in other languages so I'm trying it out in ASM.
You can see I'm using the macro CompareStrings
(source unknown; it's not mine) to set EAX
to 1 if the strings match, but when I compare EAX
to 1 using CMP
and then JE
to a label it refuses to work. Any help?
Here's the buggy code:
format PE console
;win32a.inc, win32w.inc, win64a.inc and win64w.inc
include 'win32w.inc'
entry main
; Define macros for things like printing strings ('print') and pausing (well, waiting for the user to press enter ('pause'))
macro print str {
push str
call [printf]
push 0
}
macro pause {
invoke system,'pause>nul'
}
macro getinput prompt {
print prompt
invoke gets,user_input
}
macro CompareStrings str1, str2
{
lea edi, [str2] ; edi -> address of string2
dec edi ; edi = edi - 1
.lab1: ; loop through all chars and compare each of them
inc edi ; ds:di --> next character in string2
lodsb ; al = next char from string1. loadsb increments si automatically
cmp [edi], al ; compare characters
jne .notfound ; jump out of the loop if they're unequal
cmp al, 0 ; chars are equal, but make sure we compared the entire string
jne .lab1 ; if not, continue the loop
mov eax, 1 ; else: strings are equal -> eax = 1
ret ; return; result: strings are equal
.notfound: ; chars are not equal
mov eax, 0 ; unequal -> eax = 0
ret ; return; result: strings are not equal
}
section '.text' code readable executable
main:
print header_msg
jmp input_loop
input_loop:
getinput cmd_prompt
print newline
CompareStrings user_input,cmd_exit
cmp eax, 1
je exit_cmd
jne input_loop
exit_cmd:
print header_msg
ret
section '.data' data readable writable
header_msg db "Basic Programming Language in ASM | Version 0.0.1",13,10,0
cmd_prompt db "> ",0
newline db "",13,10,0
user_input db "",0dh,0ah,0
chrarr db '%s',0dh,0ah,0
cmd_exit db 'exit',0
section '.idata' import data readable
library msvcrt,"msvcrt.dll"
import msvcrt,\
puts,"puts",\
getchar,"getchar",\
exit,"exit",\
printf,"printf",\
scanf,"scanf",\
system,"system",\
gets,"gets"
There are many problems in this program and it is not strange it crashes.
You didn't allocated enough room for the string you input. Use rb
directive to allocate some big enough space to handle your input:
user_input rb 1024
Put it at the end of the data section in order to not take place in the result executable.
I don't know how the CPP library have to be used, but probably the calling convention is not STDCALL and the parameters are not exactly these. For example gets
probably needs some kind of CPP self expandable string, not simple buffer address. Otherwise it is very easy to overflow the buffers and there is no way to check such a problem.
So, better use plain WinAPI - ReadFile and WriteFile to read and write to the console.
On the above background, it is nitpicking, but anyway:
push str
call [printf]
push 0
This push 0
looks weird here. What is is supposed to do?
Your style. Try to implement this program without using "{" and "}" characters. It will help you to understand assembly language better.