Author Topic: array  (Read 23187 times)

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2377
  • Country: us
Re: array
« Reply #15 on: February 22, 2010, 07:59:41 AM »
Hi Luke!

We can take a look at what Dr. Carter's "read_int" does...

Code: [Select]
read_int:
enter 4,0
pusha
pushf

lea eax, [ebp-4]
push eax
push dword int_format
call _scanf
pop ecx
pop ecx

popf
popa
mov eax, [ebp-4]
leave
ret

As you see, it just calls scanf, and should run on either Windows or Linux. "int_format" is just "%i", so it won't do well with 'y' or 'n'... or any other unexpected input, such as those pesky "users" are prone to do. This is a family forum, so I can't say what I think of scanf!

Dr. Carter does provide a "read_char", which will do for 'y' and 'n', and which may provide a means to replace that horrid scanf for getting a number from the user, as well. Lemme think on that...

Later,
Frank

http://www.drpaulcarter.com/pcasm to get that stuff, if you wanna play.


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2377
  • Country: us
Re: array
« Reply #16 on: February 22, 2010, 09:15:02 AM »
Indeed, I like this better than scanf!

Code: [Select]
;        call    read_int          ; read integer
; death to scanf!

xor ebx, ebx ; zero "result so far"
.next_char:
call read_char ; get a character in al
cmp al, 10 ; enter key
jz .got_int ; we're done with this number
cmp al, 'q'
jz .show_em ; we're done entering numbers

cmp al, '9'
ja .next_char ; simply ignore invalid digits
cmp al, '0'
jb .next_char

; we have a valid digit
; multiply result so far by 10
; and add in the digit
; subtracting '0' to convert char->number
; using lea...

lea ebx, [ebx + ebx * 4]
lea ebx, [ebx * 2 + eax - '0']

jmp .next_char

.got_int:
        mov [input1 + ecx * 4], ebx

This has still got a "flaw", in that it will allow the user to enter a number greater than will fit in 32 bits. No protection against overflow, it simple "rolls over" and returns your number "modulo 4G" - strictly speaking "correct", but probably unexpected. We could correct that with a less "clever" multiply and add - but scanf does no better.

Best,
Frank


Offline lukus001

  • Jr. Member
  • *
  • Posts: 16
Re: array
« Reply #17 on: February 22, 2010, 05:25:16 PM »
Hi Frank,

Personally I try to avoid using other's people codes (libraries and what not) because I don't learn as much then :3  Though I'm sure the source code is readily available to read ;).

This is how I would personally do it on linux, though very primitive and limited (Stores only a byte, has no validation of numbers, does no ascii to binary conversions etc.. etc.).

Code: [Select]
section .text
global _start

_start:

;STDin
;eax, ~ system read - 3
;ebx, ~ STD-out - 1
;ecx, ~ pointer to message storage (buffer)
;edx, ~ pointer to length of buffer
;int ~ interrupt to invoke kernel - 0x80


;STDout
;eax, ~ system write - 4
;ebx, ~ STD-out - 1
;ecx, ~ pointer to message
;edx, ~ pointer to length
;int ~ interrupt to invoke kernel - 0x80

mov ebp,esp ;save stack

prompt_add_new:
mov eax,4
mov ebx,1
mov ecx,message_add_new
mov edx,lmessage_add_new
int 0x80

get_add_new:
mov eax,3
mov ebx,1
mov ecx,buffer_add_new
mov edx,lbuffer_add_new
int 0x80

cmp BYTE [ecx],'y'
je prompt_add_int
cmp BYTE [ecx],'n'
je end

prompt_wrong_value:
mov eax,4
mov ebx,1
mov ecx,message_wrong_value
mov edx,lmessage_wrong_value
int 0x80

jmp prompt_add_new

prompt_add_int:
mov eax,4
mov ebx,1
mov ecx,message_add_int
mov edx,lmessage_add_int
int 0x80

get_add_int:
mov eax,3
mov ebx,1
mov ecx,buffer_add_int
mov edx,lbuffer_add_int
int 0x80

push DWORD [ecx]
jmp prompt_add_new

end:
mov edx,ebp ;start of stack (higher value since stack grows 'down' in memory)
sub edx,esp ;start of stack minus current stack location = number of elements stored
mov ecx,edx ;ecx is used by loop as a counter,
mov edi,temp_array ;edi is our storage location for stosb/w/d use (automatically increments to next space)
mov esi,ebp ;Same as above, but used for reading values, not storing.



start_loop:
std ; Since the stack grown 'downwards' we have to set the direction flag so ESI will be drcreased, not increased
lodsd ;load Dword from location ESI into EAX. ESI will automatically change to next location hence the use of std to decrease it.
cld ;clear direction flag, becase unlike the stack, our .bss sections 'grow' so we need stosb to increase it's location value.
stosb ;store byte value of EAX (AL) in to our memory location EDI.
loop start_loop ;loop untill ECX = 0.

mov eax,10 ;add new line
stosw ;store it
add edx,1 ;edx has the original calculation for the number of element stored, unaffected by lodsb
;so add 1 to it to account for the new line we just added above, since linux wants to know length of string when
;printing to screen.



print_array:
mov eax,4
mov ebx,1
mov ecx,temp_array
;mov edx, ;already set
int 0x80

mov eax,1
int 0x80

section .text

message_add_new: db 'Would you like to add a number? y / n',10
lmessage_add_new: equ $ - message_add_new

message_wrong_value: db 'Incorrect character, please type y / n',10
lmessage_wrong_value: equ $ - message_wrong_value

message_add_int: db 'please enter your number',10
lmessage_add_int: equ $ - message_add_int

lbuffer_add_new: dd 1
lbuffer_add_int: dd 1

section .bss

buffer_add_new: resd 1
buffer_add_int: resd 1
temp_array: resb 16000
Code: [Select]
lukus001@r31773:~/development/projects/test$ ./test2
Would you like to add a number? y / n
Maybe?
Incorrect character, please type y / n
Would you like to add a number? y / n
Yes!!!! (doesn't like capital y)
Incorrect character, please type y / n
Would you like to add a number? y / n
yes (but doesnt mind additional characters)
please enter your number
1
Would you like to add a number? y / n
y
please enter your number
22
Would you like to add a number? y / n
y
please enter your number
333
Would you like to add a number? y / n
y
please enter your number
4444
Would you like to add a number? y / n
no
1234

Should be of help to dstudentx, would still need lots of editing to make it a useful array.

By the way, does anyone else find the code boxes a bit too small height wise and textwise :3??

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2377
  • Country: us
Re: array
« Reply #18 on: February 23, 2010, 02:50:27 AM »
I think I see a subtle error in your code...

   prompt_add_int:
   mov   eax,4
   mov   ebx,1
   mov   ecx,message_add_int
   mov   edx,lmessage_add_int

-------------------------
This is okay, 'cause "lmessage+add_int" is an equ:

   message_add_int:   db   'please enter your number',10
   lmessage_add_int: equ   $ - message_add_int   
----------------------
   int   0x80

   get_add_int:
   mov   eax,3
   mov   ebx,1
   mov   ecx,buffer_add_int
   mov   edx,lbuffer_add_int

-----------------------
In this case, "lbuffer_add_int" is a variable, with "[contents]" 1.

lbuffer_add_int:   dd   1

You're putting the address in edx! A bit more than you intend to read!
----------------------------

   int   0x80

I would point out that you're reading from STDOUT, but it turns out that this doesn't matter! You can read from STDOUT, and write to STDIN, and it works. Dunno what happens if you try to read from STDERR. Must try that...

Best,
Frank