NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: muratohyes on July 02, 2014, 05:35:52 AM
-
I have the following code
segment .data
counter dd 3024
segment .bss
buffer resb 4
segment .text
global _start
_start:
mov ecx, counter
l1:
push ecx
dec dword [counter]
lea esi, [counter]
call int_to_string
mov [buffer], eax
mov eax, 4
mov ebx, 1
mov ecx, buffer
mov edx, 4
int 0x80
pop ecx
loop l1
mov eax, 1
mov ebx, 0
int 0x80
int_to_string:
add esi, 9
mov byte [esi], 10
mov ebx, 10
.next_digit:
xor edx, edx
div ebx
add dl, '0'
dec esi
mov [esi],dl
test eax, eax
jnz .next_digit
mov eax, esi
ret
As you see, I just try to count from 3024 to zero, converting the counter to string and output it on the screen. I've tried many things with no luck. Can you please show me some direction on what I can do?
-
I think your main problem was that you confused "counter" and "buffer". You were trying to convert the number to text, and put the text in [counter]. I need sleep, so this is sloppy, but I think you'll find it closer...
segment .data
counter dd 3024
segment .bss
buffer resb 12 ; 4
segment .text
global _start
_start:
mov ecx, [counter]
l1:
push ecx
dec dword [counter]
; lea esi, [counter]
lea esi, [buffer]
mov eax, [counter]
call int_to_string
; mov [buffer], eax
mov ecx, eax ; "begin print" position
xor edx, edx
getlen:
cmp byte [ecx + edx], 10
jz gotlen
inc edx
jmp getlen
gotlen:
inc edx
mov eax, 4
mov ebx, 1
; mov ecx, buffer
; mov edx, 10
int 0x80
pop ecx
loop l1
mov eax, 1
mov ebx, 0
int 0x80
int_to_string:
add esi, 9 ; counter + 9 ?
mov byte [esi], 10
mov ebx, 10
.next_digit:
xor edx, edx
div ebx
add dl, '0'
dec esi
mov [esi],dl
test eax, eax
jnz .next_digit
mov eax, esi
ret
Maybe a better attempt later... or maybe I should let you do it...
Best,
Frank
-
Thanks, the code works well now. My only problem left is the loop goes to infinity. It prints from counter to 0. After that, it first prints 4294967295 than prints 889192446 and continues to decrement from there. (889192445, 889192444 ...) As far as I know, if ECX is zero, the loop is terminated. Why is this happening?
EDIT:
If I directly write
mov ecx, 4
Instead of
mov ecx, counter
it works.
EDIT 2:
I resolved the issue by changing assignment to ecx to:
mov ecx, [counter]
Thanks, you've been a great help. For further questions, (e.g assigning this values to an array) should I open a new thread or continue within this one?
-
I'm trying to fill the array with the strings I have just converted from integers. Here's my code
segment .data
counter dd 9877
count dd 8642
array times 9876 dd '0000'
pointer dd 0
segment .bss
buffer resb 4 ; 4
segment .text
global _start
_start:
mov ecx, [count]
mov edx, array
mov dword [pointer], array
l1:
push ecx
push edx
dec dword [counter] ; decrease the counter
lea esi, [buffer]
mov eax, [counter]
call int_to_string
mov ecx, eax ; "begin print" position
xor edx, edx
getlen:
cmp byte [ecx + edx], 10
jz gotlen
inc edx
jmp getlen
gotlen:
inc edx
push eax ; printing the string converted
mov eax, 4
mov ebx, 1
int 0x80
pop eax ; printing the string converted
; copying the string to array
pop edx
mov [edx], eax
add edx, 4
pop ecx
loop l1
mov ecx, [count] ;printing the array
mov eax, array
l2:
push ecx
mov [pointer], eax
push eax
mov eax, 4
mov ebx, 1
mov ecx, pointer
mov edx, 4
int 0x80
pop eax
add eax, 4
pop ecx
loop l2
mov eax, 1
mov ebx, 0
int 0x80
int_to_string:
add esi, 9 ; counter + 9 ?
mov byte [esi], 10
mov ebx, 10
.next_digit:
xor edx, edx
div ebx
add dl, '0'
dec esi
mov [esi],dl
test eax, eax
jnz .next_digit
mov eax, esi
ret
This prints random chars when I'm printing the array. Can you tell me where I'm wrong?
-
Well... I think I may see where you're going wrong... maybe...
; okay up to here?
; copying the string to array
pop edx
mov [edx], eax
add edx, 4
As I understand it, your "int_to_string" returns what I'm calling the "start print position" - an address in "buffer" (actually outside of "buffer" - your buffer is too small - the "add esi, 9" puts us outside of "buffer". Since there's nothing after "buffer", I don't think this is a problem at present, but it isn't really "right".) Since "int_to_string" uses the same buffer for each number it converts, the same address is being stored multiple times into "array". When you try to print "array", you're printing this number - not converted to text. This is where the "garbage characters" are coming from. I think...
I think I see what's wrong, but my "quickie" attempts to fix it have been a total failure so far. Either I'm completely off-base, didn't get enough sleep, too hot to program... perhaps all of the above.
There's nothing wrong with making an "array of pointers to strings", but you have to "dereference" it properly. You might want to have two arrays, actually - one big blob of strings and an array of pointers to strings representing individual numbers. Instead of "int_to_string" getting the address of "buffer" each time, each number could be converted to a separate address in "bigbuff" - a malloced or "fake malloc" for now - address, and those addresses stored in "ptrarray". Maybe?
Keep in mind that "int_to_string" is producing a linefeed-terminated "string", and not at the "beginning" of the address that's been passed to it, but a few bytes in. There are different ways of dealing with the fact that we get the remainders in the "wrong" order. You might want to consider converting all the numbers into a "common" buffer, and copying them to their final position. This might be a good place for your "sieve" routine that eliminates duplicate digits and zeros to fit in.
Just some thoughts... probably not worth much at the moment. The research continues...
Best,
Frank
-
Thanks for ideas. I will just print zeroes to "same character/zero containing" strings, because after this operation there will be other eliminations too.
This should be printing the 4 digit numbers which doesn't contain any zeroes. It prints the first one (9876) correctly, but after that random numbers are printed out. I must be doing some pointer mistake again. Can you tell me where?
mov ecx, [count] ;printing the array
mov eax, array
l2:
push ecx
mov [pointer], eax
mov cl, 0
digit_control:
add cl, 1
cmp cl, 5
je non_zero
mov al, byte [pointer]
cmp al, '0'
je zero
add dword[pointer], 1
jmp digit_control
non_zero:
sub dword [pointer], 4
push eax
mov eax, 4
mov ebx, 1
mov ecx, [pointer]
mov edx, 4
int 0x80
pop eax
zero:
add eax, 4
pop ecx
loop l2
I later tried this but no luck, prints random characters again.
mov ecx, [count] ;printing the array
mov eax, array
l2:
push ecx
mov [pointer], eax
mov ecx, 4
mov edi, pointer
mov al, '0'
cld
repne scasb
je zero
push eax
mov eax, 4
mov ebx, 1
mov ecx, [pointer]
mov edx, 4
int 0x80
pop eax
zero:
add eax, 4
pop ecx
loop l2
-
Pushing eax before and after the zero finding solved the problem. It surely plays with eax even it doesn't seem so with the raw code.
mov ecx, [count] ;printing the array
mov eax, array
l2:
push ecx
mov [pointer], eax
push eax
mov ecx, 4
mov edi, [pointer]
mov al, '0'
cld
repne scasb
je zero
push eax
mov eax, 4
mov ebx, 1
mov ecx, [pointer]
mov edx, 4
int 0x80
pop eax
zero:
pop eax
add eax, 4
pop ecx
loop l2
-
Sorry... I had almost finished a reply when the power went out (just a thunderstorm, not the hurricane). I said some words I'm not allowed to say on the forum. When that happens, I'm too annoyed to repost right away... so I'm glad you got it working.
That was one of the things I spotted. When you alter al for the scasb, that alters eax so it doesn't point to the right place in "array". The other thing was a possible "dereferencing a pointer" problem. If it works now, perhaps that wasn't a problem at all.
If I understand it right, this "test version" works with four digits, but in the "final version" you're going to let the user choose the number of digits (I hope you're not gonna let 'em choose too many!). You might want to make that a variable now, instead of hard-coding in 4. Like for ecx for scasb, edx for sys_write... maybe "add eax, [number_of_digits]" to get to the next place in "array". Just a thought. You're doing good! We spoke of possible using a linked list to store these numbers. You still interested in that?
Best,
Frank
-
I can't thank you enough for your effort lately. I'm still having trouble on basics.
I must say I never wrote low-level code before, I even wrote C for only 2 months. I was a database administrative, specification taking, web services and forms coding guy. I've met with assembly 1 week ago, but it's a delight! After I got the basics right, I hope to help others here :) For now, I'm just trying to write the code in a static-fashion and make it work. After that I will start coding the dynamic allocations and variables, this is just a test-ride.