News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

primitive type check in MASM?

Started by Ani_Skywalker, July 21, 2010, 05:56:44 PM

Previous topic - Next topic

hutch--

Source and Destination are simple enough, When you COPY data from one register to another the SOURCE is the data to copy, the DESTINATION is where you copy the data to.


  mov eax, 1234


Copy the immediate number 1234 into the EAX register. Source is the number 1234, destination is the EAX register.

Intel assembler notation has the destination first followed by the source (in 2 operand instructions)


  add eax, ecx


Add the value in the ECX register to the value in the EAX register.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

KeepingRealBusy

Quote from: Ani_Skywalker on July 22, 2010, 11:56:54 PM
Hi guys,

Thank you for all your suggestions. And trust me, I've been reading them all. I read the masm32-editors help-files and looked up the links that jj2007 provided. Also, I've been looking up the movs, movsb and cmps commands.

Still, I am unfortunate to tell you that I'm stuck right where I were yesterday. I can't seem to pick out a byte at a time to compare it's ascii value and see if it is in the range of the ascii code for the 0-9 numbers. There is where I'm stuck at the moment. And if you could get some help from there, I would really appreciate it.

I tried code like the code below, found in the MASM32 Editors help chms. Also tried several other approaches, always with compile errors:

cld               ; set direction flag forward
    mov esi, source   ; put address into the source index
    mov edi, dest     ; put address into the destination index
    mov ecx, ln       ; put the number of bytes to copy in ecx
  ; --------------------------------------------------
  ; repeat copying bytes from ESI to EDI until ecx = 0
  ; --------------------------------------------------
    rep movsb


If you look to the code above, the first problem with is that I don't get what source and destination should be, if this is to be adapted to my current code.

Try:


   cld
   mov esi, source   ; put address into the source index
   mov edi, dest     ; put address into the destination index
  mov ecx, ln       ; put the number of bytes to copy in ecx
Again:
  lodsb
  stosb
  or al,al
  jz Exit
  dec ecx
  jnz Again
Exit:


Or to check for value ranges:


   cld
   mov esi, source   ; put address into the source index
   mov edi, dest     ; put address into the destination index
  mov ecx, ln       ; put the number of bytes to copy in ecx
Again:
  lodsb
  stosb
  cmp al,'0'
  jz Exit
  cmp al,'9'
  ja Exit
  dec ecx
  jnz Again
Exit:


Dave.



hutch--

You should avoid using LODS STOS without the REP prefix as they are very slow. Incremented pointers use less registers and are faster.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

dedndave

they are nice in areas when speed isn't critical, though
they are single byte instructions and they increment or decrement the index register for you    :bg

hutch--

Yes but its sloppy and slow 1980s technology, incremented pointters are simple enough to use, use less registers and are faster. the 8088 is dead !  :bg
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

dedndave

 we finally found something to disagree on   :lol
i don't think it's sloppy
if i wanted to write a special command-line parser.....
how fast and how many times do you need to parse the command-line, anyways ?
LODSB / STOSB are perfect for that kind of loop
they keep the code small when speed is not an issue

Ani_Skywalker

.486                                   
.model flat, stdcall                 
option casemap :none

include \masm32\include\windows.inc     
include \masm32\macros\macros.asm

include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc

includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib


.data?
var1 dd, 0
var2 dd, 0
container dd, 0

.code

start:
       
    mov var1, sval(input("Enter the first number: "))

   cld
   mov esi, var1   ; put address into the source index
   mov edi, container     ; put address into the destination index
   mov ecx, 1       ; put the number of bytes to copy in ecx
   Again:
   lodsb
   stosb
   cmp al,'0'
   jz Exit
   cmp al,'9'
   ja Exit
   dec ecx
   jnz Again
   Exit:

    mov var2, sval(input("Enter the second number: "))
    print chr$(13,10)
    print str$(var1)
    print chr$(' ')
    print str$(var2)
    print chr$(13,10,13,10)

    xor eax, eax

    add eax, var1
    add eax, var2

    print str$(eax)
    print chr$(13,10,13,10)

mov eax, input("Press 'Enter' to exit. ")

exit

end start


The above code does compile but I get an error during running, just after you entered the first number, meaning it starts to bug here:

cld
   mov esi, var1   ; put address into the source index
   mov edi, container     ; put address into the destination index
   mov ecx, 1       ; put the number of bytes to copy in ecx
   Again:
   lodsb
   stosb
   cmp al,'0'
   jz Exit
   cmp al,'9'
   ja Exit
   dec ecx
   jnz Again
   Exit:


The above code I got by you guys and it looks some those approaches I tried myself. Now, can you guys see why it goes wrong here?

Ani_Skywalker

Quote from: hutch-- on July 23, 2010, 12:47:13 AM
Source and Destination are simple enough, When you COPY data from one register to another the SOURCE is the data to copy, the DESTINATION is where you copy the data to.

Thank you Hutch, however, that part I knew. What I did not understand is how to adapt my code to that.

For example, I don't have a DESTINATION since I do not want to copy the data. I just want to parse the SOURCE byte by byte and condition each byte to see if it is in the range of ascii 0-9. I like to do this to be able to identify numbers from all other characters. So, since I don't need it, but every informative source I looked through use this approach, I am confused  :(

jj2007

mov ecx, 1       ; put the number of bytes to copy in ecx
...
dec ecx

Your loop will run exactly once.

Ani_Skywalker

Quote from: jj2007 on July 23, 2010, 12:39:47 PM
mov ecx, 1       ; put the number of bytes to copy in ecx
...
dec ecx

Your loop will run exactly once.

Yes indeed. But why does it crash after? And how do I get it to run as long as there is no bytes left to loop? :)

hutch--

Ani,

You basically check each byte against two values, the highest and the lowest in the ascii/ansi range you are after to filter only number characters. In the masm32 help file there is an ascii/ansi charcters chart and there you will find the range, if the byte value is lower than 48 or greater than 57 then its not a number.

To do this you read each byte and compare it against the upper and lower limits, you allow characters that are within the limits, you disallow characters that are not.

Construct a loop that reads the characters up to the terminator which should be ascii 0 and with the characters you evaluate, only accept those that are within those limits.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Ani_Skywalker

Quote from: hutch-- on July 23, 2010, 01:10:29 PM
Construct a loop that reads the characters up to the terminator which should be ascii 0 and with the characters you evaluate, only accept those that are within those limits.

But it is here I fail :( The other part about checking for the byte to be within ascii 48-57 I've figured out. But at the moment, I'm stuck on how to separate a byte to read, do some comparison on it and then go back to read the next byte.

For example, look this again and I try to comment more on this, which part I understand and which I don't.


   mov esi, var1   ; put address into the source index
   mov edi, container     ; put address into the destination index
   mov ecx, 1       ; put the number of bytes to copy in ecx
   

Oki, here is where I'm stuck. How do I get this to loop more then once? When I used "ln" before, I got compile-error. I'm sure there should be some index-mover or something that points to the next byte.



Again:
   lodsb
   stosb
   cmp al,'0'
   jz Exit
   cmp al,'9'
   ja Exit
   dec ecx
   jnz Again
   Exit:


Above is still to come, but I understand "Again" is a loop, it looks very much like "Labels" that I've come across in some other languages (Java, C#, C++). At the moment, let's ignore this part. How do I solve my first problem, the first one?

I've read the tutorials, and I can tell they DO bring this up, problem is, I don't get it since I'm stupid  :(

jj2007

sval gives you already an integer value. You want to examine the string returned by input. Try this:

.data?
var1 dd ?
var2 dd ?
container dd ?
TheBuffer db 80 dup(?)

.code

start:
mov esi, input("Enter the first number: ")
cld
mov container, offset TheBuffer
mov edi, container ; put address into the destination index
push edi ; stosb changes edi, so we save a copy
mov ecx, 80 ; put the number of bytes to copy in ecx

Again:
lodsb
stosb
cmp al, 0 ; 0, not '0'
jz Exit
cmp al, '9'
ja Exit
cmp al, '0'
jb Exit
dec ecx
jnz Again

Exit:
mov byte ptr [edi-1], 0 ; delimit your input string
pop edi
mov var1, sval(edi) ; convert string to integer
print "Result="
print str$(var1), 13, 10
exit

hutch--

Here is a simple test piece that filters so you only have numbers in the destination. I was trying to avoid writing it for you as you should learn enough and write your own.


IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc



    chfilter PROTO :DWORD,:DWORD



    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL buffer[64]:BYTE
    LOCAL ptxt  :DWORD

    mov ptxt, ptr$(buffer)

    fn chfilter,"1b2g3h4k4m5k7k8d9a0",ptxt

    print ptxt,13,10

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

chfilter proc src:DWORD,dst:DWORD

    push esi
    push edi

    mov esi, src
    mov edi, dst
    sub esi, 1

  lbl0:
    add esi, 1
    mov al, [esi]               ; read byte into register
    test al, al                 ; check if its zero
    jz quit
    cmp al, 48
    jl lbl0                     ; is it less than 48 ?
    cmp al, 57
    jg lbl0                     ; is it greater than 57 ?
    mov [edi], al               ; if within range, write it to destination buffer
    add edi, 1
    jmp lbl0

  quit:

    mov BYTE PTR [edi], 0

    pop edi
    pop esi

    ret

chfilter endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php