NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: maplesirop on February 25, 2013, 01:46:31 AM
-
mov eax, 4
mov ebx, 1
mov ecx, promptUser
mov edx, len
int 0x80
mov eax, 3
mov ebx, 0
mov ecx, userInput
mov edx, 10
int 0x80
mov eax, 4
mov ebx, 1
int 0x80 : everything works until here
cmp ecx, 1
jle elseif
cmp ecx, 20
jge elseif
mov eax, 4
mov ebx, 1
mov ecx, if
mov edx, ifLen
int 0x80 : doesn't work
label1: cmp ecx, 21
jle aelseif
cmp ecx, 41
jge aelseif
mov eax, 4
mov ebx, 1
mov ecx, aIf
mov edx, aIfLen
int 0x80 : doesn't work
Do I have to add this: str2int data so that we can compare ecx with decimal numbers?
Also do I have to remove int0x80, because it erase the value of ecx?
mov eax, 4
mov ebx, 1
mov ecx, promptUser
mov edx, len
int 0x80
mov eax, 3
mov ebx, 0
mov ecx, userInput
str2int data : converts userInput intro decimal int
mov edx, 10
int 0x80
mov eax, 4
mov ebx, 1
int 0x80 : everything works until here
cmp ecx, 1
jle elseif
cmp ecx, 20
jge elseif
mov eax, 4
mov ebx, 1
mov ecx, if
mov edx, ifLen
int 0x80 : doesn't work
label1: cmp ecx, 21
jle aelseif
cmp ecx, 41
jge aelseif
mov eax, 4
mov ebx, 1
mov ecx, aIf
mov edx, aIfLen
int 0x80 : doesn't work
-
You will get more help if you post your complete code, that includes all your variables, not just code snippets.
mov eax, 3
mov ebx, 0
mov ecx, userInput
str2int data : converts userInput intro decimal int
mov edx, 10
int 0x80
eax, is the type of system call, but str2int, I am guessing, returns the dword in eax so the value 3 for the system call is now overwritten.
-
; prompt user
mov eax, 3
mov ebx, 0
mov ecx, userInput
str2int data : converts userInput intro decimal int
mov edx, 10
int 0x80
;...
It looks like you've inserted this macro (from nagoa.inc?) into the middle of a sys_read. It's going to work better if you finish reading the string before you convert it to integer. :)
This macro expects a zero-terminated string (as its parameter - where you've got "data), which sys_read is not going to give you (we can zero-terminate it easily). It puts the number in eax - ecx is going to be zero on exit from the macro. I can't imagine that your next sys_write is going to work, although the comment says it does...
Then you seem to be checking if ecx is between 2 and 19 (inclusive). It isn't clear where you jump to if ecx is less than or equal to 1, or if it's greater than or equal to 20. Then you print something(?) and fall through to checking if ecx is between 22 and 40 - it isn't, because you've changed it in printing "if".
You shouldn't have to remove any int 0x80 - it won't, in itself, change ecx... although you may need to change ecx to use it.
If you're finding that Linux isn't going to work for you, you may need to use WriteFile instead of sys_write and ReadFile instead of sys_read. In between interactions with the OS, the code should be pretty much the same... if that's any help. :)
Best,
Frank
P.S. Gunner has picked up another problem that I missed. Yeah, show us more of the code!
-
segment .data
promptUser db "enter something", 10, 0
len equ $ -promptUser
if db "ok", 10, 0
ifLen equ $ -if
aif db "ok", 10, 0
aifLen equ $ -aif
segment .bss
userInput 1: it's 1 char
global _start
_start
mov eax, 4
mov ebx, 1
mov ecx, promptUser
mov edx, len
int 0x80
mov eax, 3
mov ebx, 0
mov ecx, userInput
str2int data : converts userInput intro decimal int
mov edx, 10
int 0x80
mov eax, 4
mov ebx, 1
int 0x80 : everything works until here
cmp ecx, 1
jle elseif
cmp ecx, 20
jge elseif
mov eax, 4
mov ebx, 1
mov ecx, if
mov edx, ifLen
int 0x80 : doesn't work
label1: cmp ecx, 21
jle aelseif
cmp ecx, 41
jge aelseif
mov eax, 4
mov ebx, 1
mov ecx, aIf
mov edx, aIfLen
int 0x80 : doesn't work
-
; prompt user
mov eax, 3
mov ebx, 0
mov ecx, userInput
str2int data : converts userInput intro decimal int
mov edx, 10
int 0x80
;...
It looks like you've inserted this macro (from nagoa.inc?) into the middle of a sys_read. It's going to work better if you finish reading the string before you convert it to integer. :)
This macro expects a zero-terminated string (as its parameter - where you've got "data), which sys_read is not going to give you (we can zero-terminate it easily). It puts the number in eax - ecx is going to be zero on exit from the macro. I can't imagine that your next sys_write is going to work, although the comment says it does...
Then you seem to be checking if ecx is between 2 and 19 (inclusive). It isn't clear where you jump to if ecx is less than or equal to 1, or if it's greater than or equal to 20. Then you print something(?) and fall through to checking if ecx is between 22 and 40 - it isn't, because you've changed it in printing "if".
You shouldn't have to remove any int 0x80 - it won't, in itself, change ecx... although you may need to change ecx to use it.
If you're finding that Linux isn't going to work for you, you may need to use WriteFile instead of sys_write and ReadFile instead of sys_read. In between interactions with the OS, the code should be pretty much the same... if that's any help. :)
Best,
Frank
P.S. Gunner has picked up another problem that I missed. Yeah, show us more of the code!
thanks
umm... do i have to convert ecx into a decimal integer? if so, what do i need to do?
Basically I have to check what the character entered is
if its ASCII code is between @ and c, i print something. If it's between d and A, I print something and then so on...
-
Oh!
Here's what I thought you were trying to do:
; nasm -f elf32 myfile.asm
; ld -o myfile myfile.o (-melf_i386 for 64-bit systems)
global _start
;;================================
;; MACRO str2int int2str by Written by mastercpp.
;;================================
%macro str2int 1
push ebx ;
push esi ;
push edi ;
mov ebx, 0
mov ecx, 0
xor eax,eax
mov ebx,0000000Ah
; mov esi,offset %1
; offset??? who said that swearword? :)
mov esi, %1
%%ConvertLoop:
movzx ecx,byte [esi] ;Zeichen laden.
test ecx,ecx
jz short %%ExitConvertLoop ;0 => Exit
inc esi
sub cl,30h ;0-9...
mul ebx ;Ergebnis * 10
add eax,ecx ;+ nächste Ziffer
jmp short %%ConvertLoop
%%ExitConvertLoop:
pop edi
pop esi
pop ebx
%endmacro
%macro int2str 2
push ebx ;
push esi ;
push edi ;
%%start:
mov eax, %1
xor ecx, ecx
mov ebx, 000ah
%%DecConvert:
xor edx, edx
div ebx
add edx, 0030h
push edx
inc ecx
or eax, eax
jnz short %%DecConvert
mov edi, %2
mov edx,ecx
%%SortDec:
pop eax
stosb
loop %%SortDec
mov eax, 0h
stosb
pop edi
pop esi
pop ebx
%endmacro
;;================================
;; mastercpp end macros
;;================================
section .data
promptUser db "you know what to do", 10
len equ $ - promptUser
if db 10, "between 2 and 19", 10
ifLen equ $ - if
aIf db 10, "between 22 and 40", 10
aIfLen equ $ - aIf
section .bss
theNumber resd 1
userInput resb 11
section .text
_start:
mov eax, 4
mov ebx, 1
mov ecx, promptUser
mov edx, len
int 0x80
mov eax, 3
mov ebx, 0
mov ecx, userInput
mov edx, 10
int 0x80
push eax ; save the length
mov byte [ecx + eax - 1], 0 ; zero-terminate the sucker!
str2int userInput ; converts userInput intro decimal int
mov [theNumber], eax
mov eax, 4
mov ebx, 1
mov ecx, userInput
pop edx ; get the length back
int 0x80 ; everything works until here
mov ecx, [theNumber]
cmp ecx, 1
jle elseif
cmp ecx, 20
jge elseif
mov eax, 4
mov ebx, 1
mov ecx, if
mov edx, ifLen
int 0x80 ; doesn't work
jmp endif
elseif: ; ?
label1: cmp ecx, 21
jle aelseif
cmp ecx, 41
jge aelseif
mov eax, 4
mov ebx, 1
mov ecx, aIf
mov edx, aIfLen
int 0x80 ; doesn't work
jmp endif
aelseif:
; print "none of the above"
endif:
mov eax, 1
xor ebx, ebx
int 0x80
No, if you want to check ascii codes, you don't have to convert to a number. However, ecx is the address of where the victim ("user", I mean!) put his masterwork. You could do something like...
cmp byte [ecx], '@'
jb someplace
or perhaps better...
mov al, [ecx] ; or the name of the buffer
cmp al, '@'
jb someplace
cmp al, '9'
ja someplace
; do your @ - 9 thing
jmp outtahere
someplace:
cmp al, ... whatever
Notice I changed jg and jl to ja and jb. jg and jl are for signed comparisons, ja and jb are for unsigned comparisons. Since we won't be seeing any negative ascii codes, unsigned is correct. It won't cause you any trouble in this case, either way. I left it as signed (and exclusive) in "my version", even though "mastercpp"s macro won't return negative numbers, 'cause I was gonna show you a better way... but that's not what you're trying to do...
See, like Gunner told you, we can help you better if you give us more information! :)
After looking at your latest code...
...
userInput 1: it's 1 char
I suppose you mean "resb". With the colon in there instead of a semicolon, it won't even assemble!
mov edx, 10
int 0x80
Overflowing your buffer a bit there!
Best,
Frank
-
thanks, but uhm I want to keep things simple and the code you've given me is a little bit too complex for me right now. also, do i have to convert a char to a number if I want to use decimal number in cmp statements? and is there a way to convert a char into a int decimal without using a macro? I only want to use "native" codes.
-
thanks, but uhm I want to keep things simple and the code you've given me is a little bit too complex for me right now.
Okay. I try to keep the code as simple as possible to do the job. My problem, at this point, is that I don't know what the "job" is. I thought I knew, but I'm getting more and more confused as I go along. Can we start over? What are you trying to do?
also, do i have to convert a char to a number if I want to use decimal number in cmp statements?
A number is a number. You can represent a number as decimal, or hex, or octal, or binary... or as an ascii character, if it's a printable ascii character. Still the same number.
cmp byte [ecx], '@'
cmp byte [ecx], 64 ; decimal
cmp byte [ecx], 0x40 ; hexadecimal
cmp byte [ecx], 100q ; octal
cmp byte [ecx], 0100_0000b
All of those lines produce exactly the same code.
and is there a way to convert a char into a int
A "char" is 8 bits. What's an "int"? 32 bits? You can sign extend 8 bits to 32 bits. You can zero extend it, too... but then it'd be an "unsigned int". If the "char" is "true ascii" (high bit clear), it wouldn't make any difference.
decimal
Sure, you can represent it as decimal.
without using a macro?
Sure. In fact, I think a macro is a poor way to do it. A subroutine would be better, IMO. But I'm not certain whether you need to do anything at all.
I only want to use "native" codes.
I don't know which ones are "native". A macro is just cut-and-paste. You never "have" to use a macro, they're just a convenience...
Best,
Frank
-
I have to enter an input from the keyboard and look if the char is between @ and a or between b and h or between h and z.
-
Okay... you know how to get input from the keyboard (I guess). Forget about "converting" anything to anything - that was a false alarm. Where you seem to be going wrong is thinking that the character is going to be in ecx. It is not, it's going to be in memory pointed to by ecx - in [ecx] if you look at it that way. Nasm is going to need to be told "byte", since [ecx] could point to any size value. If we use an 8-bit register, Nasm knows we want "byte" without us having to say so. That's the way I'd do it...
mov al, [ecx]
Or... it might be clearer if we do...
mov al, [userInput]
ASSuming that ecx still points to userInput, as it was for the sys_read, they're the same thing. Then you can go on to compare the character to various things. You can look up the number associated with '@' (etc.) and use the numbers, but I think your code will be a lot more readable if you just call it '@'. Programmer's choice.
Randy Hyde tells me that this "if" concept is something beginners have a lot of trouble with. We don't have an instruction that says "if condition, do these next few instructions". What we have are instructions that say "if condition, goto". I know "goto" has a bad reputation in some circles, but that's the instruction we have. So what we need to do is "if not condition, goto someplace after these next few instructions". Read over some of the examples above with that in mind and see if it becomes any clearer.
After doing the "if clause", we may want to "fall through" into the following code, or we may want to "jmp someplace else". Think through what you want to do in each case - essentially the difference between having an "else" or "elif" clause or not... Keep in mind that we WILL fall through unless we do something else...
We've been discussing Linux code. Last we heard from you on the subject, you were having trouble running Linux. If you can run some simple programs, you can learn a lot by "trying things". If you can't, it's going to be a lot harder! Since you've been posting code that won't even assemble, I suspect that you may still be having trouble with that. If it were me, I'd format the accursed Windows drive and install Linux, but that may not be a good solution for you. Can you run Linux from a "live CD"? Can you install Dosbox? (I can't get DosBox to build, so I haven't been able to try it) Dos is pretty useless, but some simple user I/O is pretty easy to learn. Windows isn't "that" hard to learn. This'll go a lot easier for you if you can "try things"!
Best,
Frank
-
omg, thanks. you made my day. i was so depressed this morning, now i am happy as hell.