Author Topic: assembly code not reading 32 bit but 16 bits only  (Read 10595 times)

Offline sandeepyadav

  • Jr. Member
  • *
  • Posts: 8
assembly code not reading 32 bit but 16 bits only
« on: August 05, 2013, 05:39:59 PM »
Code: [Select]
section .data

array1 db 10,'Enter 10 hexadecimal numbers(32 bit):',10,13
array1_len: equ $-array1

array2 db 10,'Enter 10 hexadecimal numbers(64 bit):',10,13
array2_len: equ $-array2

disp_array1 db 10,'32 bit array is:',10,13
disp_array1_len: equ $-disp_array1

disp_array2 db 10,'64 bit array is:',10,13
disp_array2_len: equ $-disp_array2

nxline db 10

section .bss

_array1 resd 10
_array2 resq 10

index resd 1 ;to traverse array
index1 resq 1
count resd 1                     ;previously it was resb
;address resd 1 ;to store array pointer

;val resd 1
;val1 resq 1

buffer_32 resq 1
buffer_32_len: equ $-buffer_32
buffer_64 resq 1
buffer_64_len: equ $-buffer_64

dnum_buff resb 09

%macro write_string 2
mov eax,4 ;System call for write
mov ebx,1 ;standard output stream
mov ecx,%1 ;message start address
mov edx,%2 ;message length
int 80h
%endmacro

%macro read_string 2
mov eax,3 ;System call for read
mov ebx,0 ;standard input stream
mov ecx,%1 ;store in buffer
mov edx,%2 ;length of string being stored
int 80h
%endmacro

section .text

global _start

_start:

write_string array1, array1_len

mov ecx, 0Ah
mov [count],ecx

mov dword[index], 0
acpt1:
read_string buffer_32,4         ; buffer_32 reading 16 bits only

mov eax, [buffer_32]
mov ecx, [index]
mov [_array1+ 4*ecx],eax      ;previously written esi
mov ecx, [index]
inc ecx
mov [index], ecx

mov ecx,[count]
dec ecx
mov [count],ecx
cmp ecx,0
je next1
jmp acpt1 ;loop to accept numbers
« Last Edit: August 05, 2013, 05:50:50 PM by Frank Kotler »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: assembly code not reading 32 bit but 16 bits only
« Reply #1 on: August 05, 2013, 06:11:24 PM »
Hi Sandeep,

I put "code tags" around your code. Hope I didn't screw anything up.

In any case, you appear to be allowing only 4 characters per entry. This isn't going to be enough to represent a 32-bit number (or 64-bit!) in hex. (you'll need bigger buffers)

What do you intend this to do? Are you aware of the difference between the characters representing a number, and the number itself?

Best,
Frank


Offline sandeepyadav

  • Jr. Member
  • *
  • Posts: 8
Re: assembly code not reading 32 bit but 16 bits only
« Reply #2 on: August 06, 2013, 04:32:46 AM »
Hello Frank.
                I am  unaware of the difference between the characters representing a number, and the number itself. I want to accept an array & display it. My displaying part of code isn't working because buffer_32 isn't reading complete input. I am not getting how to read hex number from terminal.

Thanks & regards,
Sandeep

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: assembly code not reading 32 bit but 16 bits only
« Reply #3 on: August 06, 2013, 08:26:36 AM »
Well... you can't read anything from the terminal (or console. or stdin) but text. If the pesky user (you) types "123", we read into the buffer the character '1' (31h), the character '2' (32h), and the character '3' (33h). They're numbers, of course, but they're the ascii codes of the numbers we're looking for, not the numbers we're looking for...

Since you're on Linux, you can do "man ascii" to see an ascii table. As you can see, the lower numbered ones are "control codes" - you already know one of them, 0Ah or 10 decimal, the linefeed character (you call it "nxline" in your code). There are a couple of other interesting control codes, mostly they're not - we want to avoid writing them to stdout, 'cause they'll mess up our display. The "printable characters" start at 20h with the space. Then there's some punctuation, and at 30h we come to the character '0'. The other characters representing decimal digits follow, then there's more punctuation and 'A' at 41h. You may want to allow the user to use either 'A' - 'F' or 'a' - 'f'.

We usually interpret that "123" as decimal (multiply by 10 for each digit), but we can interpret it as hex... We need to remember that each character represents 4 bits - a number beween 0 and 15 (decimal), not a number between 0 and 10! To do decimal, we have to multiply and divide by 10, for hex we have to multiply and divide by 16... but we can do that with shifts and rotates - easier in a way (beginners have a lot of trouble with "div"!).

Now we have to look at how sys_read works. In your macro, you're putting the second parameter in edx - you're using 4. But sys_read won't return until the user hits "enter", and the linefeed generated by that is included in the count! If the pesky user types more than 3 characters and "enter", only 4 go into your buffer and anything more stays in the OS's buffer ("keyboard buffer"?), ready to be read next time. If you type "FFFFFFFF" trying to get a 32-bit number, the first "FFFF" goes into your buffer and is transferred to your array at index 0, then the next loop gets the second "FFFF" - goes to index 1 then the next loop gets the linefeed (0Ah or 10 decimal), and that goes into index 2 (where it isn't going to display anything, when you get to that). You probably want to convert it to the number 0FFFFh, (or 0FFFFFFFFh if you had it all) before you transfer it to your array - 0FFFFFFFFh will fit in eax, the characters "FFFFFFFF" won't!

I think that's the root of your problem. Make your buffer bigger - 9 bytes for 32-bit numbers, 17 bytes fot 64-bit numbers (you sure you want to do that? It'll take two registers... or switch to 64-bit code). Won't hurt if the buffer is too big. Then "read_string buffer 9", then walk down the buffer a character at a time, checking each for the '0'-'9', 'A'-'F', 'a'-'f' range, and subtracting the correct amount to make it a number between 0 and 15 (decimal) - 4 bits. Mask this number off to just the 4 bits we want (and eax, 0Fh). Did I mention that we need to zero out a register for "result so far" before we start? Yeah, and now that we've got a valid number, shift the "result so far" left by 4 (multiply by 16). Then "or" the "result so far" with our new 4 bits. Repeat until done. I like to quit if I encounter anything outside the "valid" ranges - that'll cover a zero-terminated string or a linefeed-terminated "string" like sys_read gives you... or garbage from the pesky user You might want to count characters, in addition, to avoid overflow.

I don't think I have an example at hand, but I could probably come up with one if you need it. Give it a shot first.

Or... we could "just call scanf" (they make me say that :) ).

Best,
Frank


Offline sandeepyadav

  • Jr. Member
  • *
  • Posts: 8
Re: assembly code not reading 32 bit but 16 bits only
« Reply #4 on: August 08, 2013, 08:02:26 AM »

     Thanks Frank, It's working.  :)

     Regards,
     Sandeep