News:

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

Need help cuz I'm a rookie to assembler

Started by daniellam, November 06, 2008, 07:08:55 AM

Previous topic - Next topic

daniellam

Hi everyone!
I'm new to x86 assembly programming. So far I learn some basic skills from the textbook, "Assembly Language For Intel-Based Computers", 4th edition. I read up to chapter 5 about the link library provided by the book. For every program I made was using the book's include directive, "INCLUDE Irvine32.inc". Recently I need to display a table with decimal and hexadecimal number conversion. So, in this program, I used the "WriteDec" and "WriteHex" procedures from the link library to shows the hex number. However, I just need to show the number ranging from 0-255. To show the number, I need to put the number into EAX register and CALL WriteHex.
For example,
     MOV EAX, 48
     CALL WriteHex

The result showing is "00000030" in hex, but i just want the lower 8 bits in EAX, which is "30".
Q: So, what should I do to extract 8-bit "30" from 32-bit "00000030" and print it to the standard output? (I cannot use WriteHex since it will show the entire 32bit only)

p.s.Is there a different way to display values in a specific register without using the procedures from the link library, e.g. WriteHex, WriteString, etc?
I'm using both VS 2005 and MASM32 assembler.

MichaelW

You could try taking a look at the source for the WriteHex procedure in Irvine32.asm. From that you should be able to create your own procedure (with a different name) that will display only 2 digits, as well as learn one method of converting a value in a register to a hex string.
eschew obfuscation

BlackVortex

Or checkout the bitwise operations, like AND, if you really want to keep the last 8 bit-digits only  ... and still use a 32-bit register.

KeepingRealBusy

I think he is more interested in editing the output to the last two characters than in restricting the register value.

Dave.

MichaelW

Quote from: BlackVortex on November 06, 2008, 07:18:53 PM
Or checkout the bitwise operations, like AND, if you really want to keep the last 8 bit-digits only  ... and still use a 32-bit register.

The numbers will be contained entirely in the last 8 bits. The problem is the leading zeros in the string.
eschew obfuscation

Mark Jones

Daniellam, you could try tinkering with this code snippet:

http://www.masm32.com/board/index.php?topic=9062.msg65629#msg65629

The "TextToHex" proc calls the "b2hex" proc for each byte needing conversion. Experiment. :U

Or check out http://www.masm32.com/board/index.php?topic=4475.0 or http://www.masm32.com/board/index.php?topic=7741.0 ... search for "convert hex" for even more.
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

herge

 Hi  daniellam:

try this:


; BINIHEX.ASM Saturday, November 08, 2008 6:22 PM
; by herge
include \masm32\include\masm32rt.inc
.data
sOut    db 20 dup (0)
        db 0
CrLf    db 13, 10 ,0       
.code
rotate proc
; esi > String Output(Print Buffer)
; ch number of digits
; cl number of bits
rol bx,cl ; left digit to right digit
mov al,bl ; move to AL
and al,0Fh; mask off left digit
;From 8080a/8085 assembly language
;programming pg 7-3
; Lance A. Leventhal
; Binary digit to Ascii Digit
; with no jumps
add al,90h ; add BCD 90
daa ; decimal adjust
adc al,40h ; add BCD 40 and carry
daa ; decimal adjust
mov byte ptr [esi] , al
inc esi ; > next digit
dec ch ; done 4 digits
jnz rotate ; yet
      ret
rotate endp
BINIHEX proc
;
; subroutine to convert biniary number in BX
; to HEX on console screen
; esi > Output String
push eax
push ecx
push edx
mov cx,0404h
; ch number of digits
; cl number of bits
      call rotate
pop edx
pop ecx
pop eax
ret
BINIHEX endp
DUMP_BYTE proc
; Dump BH to Buffer
; esi > Output String
; uses BINIHEX logic
push eax
push ecx
push edx
mov cx, 0204h
    call rotate
pop edx
pop ecx
pop eax
ret
DUMP_BYTE endp
DUMP_WORD proc
; Dump word BX to screen
; Print 'H' after Hex digits
; esi > Output String
pushf
push eax
push ecx
push edx
call BINIHEX
mov al,'H'
mov byte ptr [esi] , al
inc esi
      mov   al, 0
      mov   byte ptr [esi] , al
      inc   esi
pop edx
pop ecx
pop eax
popf
ret
DUMP_WORD endp
Start:
    lea esi, sOut
    mov bh, 255 ; Note BH NOT BL!!!
    call DUMP_BYTE
    lea esi, sOut
    invoke StdOut, esi
    getkey
    invoke StdOut, offset CrLf
    mov bx, 01234h
    mov esi, offset sOut
    call DUMP_WORD
    lea esi, sOut
    invoke StdOut, esi
    invoke StdOut, offset CrLf
    inkey
    exit
    end Start



Regards herge
// Herge born  Brussels, Belgium May 22, 1907
// Died March 3, 1983
// Cartoonist of Tintin and Snowy

GregL

#7
herge,

I was playing around with your code, and I came up with a procedure, dwtoh, that is derived from the code you posted. It works fine but, on my system, its three times slower than the dw2hex procedure in the masm32 library. It was fun writing it though. [edit] And maybe danielm can use btoh.


INCLUDE \masm32\include\masm32rt.inc

INCLUDE Timers.asm

.DATA

    ALIGN 4
    bVal    BYTE 12h
    ALIGN 4
    wVal    WORD 1234h
    ALIGN 4
    dwVal   DWORD 12345678h
    ALIGN 4
    szOut   BYTE 32 DUP(0)
    szCrLf  BYTE 13, 10 ,0

.CODE

;----------------------------------------
btoh PROC pB:PTR BYTE, pszBuffer:PTR BYTE
    mov ecx, pszBuffer
    mov eax, pB
    ;xor edx, edx  ; not really necessary
    mov dh, BYTE PTR [eax]
    REPEAT 2
        rol dx, 4
        mov al, dl   ; move to AL
        and al, 0Fh  ; mask off left digit
        add al, 90h  ; add BCD 90
        daa          ; decimal adjust
        adc al, 40h  ; add BCD 40 and carry
        daa          ; decimal adjust
        mov BYTE PTR [ecx], al
        inc ecx      ; > next digit
    ENDM
    mov BYTE PTR [ecx], 0
    ret
btoh ENDP
;----------------------------------------
wtoh PROC pW:PTR WORD, pszBuffer:PTR BYTE
    mov ecx, pszBuffer
    mov eax, pW
    ;xor edx, edx  ; not really necessary
    mov dx, WORD PTR [eax]
    REPEAT 4
        rol dx, 4
        mov al, dl   ; move to AL
        and al, 0Fh  ; mask off left digit
        add al, 90h  ; add BCD 90
        daa          ; decimal adjust
        adc al, 40h  ; add BCD 40 and carry
        daa          ; decimal adjust
        mov BYTE PTR [ecx], al
        inc ecx      ; > next digit
    ENDM
    mov BYTE PTR [ecx], 0
    ret
wtoh ENDP
;----------------------------------------
dwtoh PROC pD:PTR DWORD, pszBuffer:PTR BYTE
    mov ecx, pszBuffer
    mov eax, pD
    mov edx, DWORD PTR [eax]
    REPEAT 8
        rol edx, 4
        mov al, dl   ; move to AL
        and al, 0Fh  ; mask off left digit
        add al, 90h  ; add BCD 90
        daa          ; decimal adjust
        adc al, 40h  ; add BCD 40 and carry
        daa          ; decimal adjust
        mov BYTE PTR [ecx], al
        inc ecx      ; > next digit
    ENDM
    mov BYTE PTR [ecx], 0
    ret
dwtoh ENDP
;----------------------------------------

  Start:

    INVOKE btoh, ADDR bVal, ADDR szOut
    INVOKE StdOut, ADDR szOut
    INVOKE StdOut, ADDR szCrLf

    INVOKE wtoh, ADDR wVal, ADDR szOut
    INVOKE StdOut, ADDR szOut
    INVOKE StdOut, ADDR szCrLf
    INVOKE StdOut, ADDR szCrLf

    timer_begin 100000, HIGH_PRIORITY_CLASS
     INVOKE dwtoh, ADDR dwVal, ADDR szOut
    timer_end
    push eax
    INVOKE StdOut, SADD("dwtoh = ")
    pop eax
    INVOKE StdOut, udword$(eax)
    INVOKE StdOut, ADDR szCrLf

    INVOKE StdOut, ADDR szOut
    INVOKE StdOut, ADDR szCrLf
    INVOKE StdOut, ADDR szCrLf

    timer_begin 100000, HIGH_PRIORITY_CLASS
     INVOKE dw2hex, dwVal, ADDR szOut
    timer_end
    push eax
    INVOKE StdOut, SADD("dw2hex = ")
    pop eax
    INVOKE StdOut, udword$(eax)
    INVOKE StdOut, ADDR szCrLf

    INVOKE StdOut, ADDR szOut
    INVOKE StdOut, ADDR szCrLf

    inkey SADD(13,10,"Press any key to exit ... ")
    exit

END Start


askm

Coders just want to have fun...

reinventing the wheels ?

Dont reinvent at the wheels,

instead where it meets the road...

at the tires, ie, in this case, the output ?

Just a thought.

herge


Hi All:

We are forgetting the easiest solution why not start in the
miidle of the print buffer. It's very unlikely this position
is going to move.
Either hard code it or search for a byte greater than
Ascii Zero and before the ending NULL(Zero Byte).

Regards herge
// Herge born  Brussels, Belgium May 22, 1907
// Died March 3, 1983
// Cartoonist of Tintin and Snowy

herge

 Hi All:

using dw2hex from c:\masm32\m32lib\dw2hex.asm

; ########################################################################
;
;               This original module was written by f0dder.
;
;      Part of the code has been optimised by Alexander Yackubtchik
;
; ########################################################################
    include \masm32\include\masm32rt.inc

    .386
     option casemap :none   ; case sensitive
    .data
HexIn dd 0
HexOut db 20 dup(0)
       db 0
CrLf db 13, 10, 0       
    .code

; ########################################################################

dw2hex proc source:DWORD, lpBuffer:DWORD
    push esi
    mov edx, lpBuffer
    mov esi, source
    xor eax, eax
    mov ecx, eax
    mov [edx+8], al         ; put terminator at correct length
    mov cl, 7               ; length of hexstring - 1
  @@:
    mov eax, esi            ; we're going to work on AL
    and al, 00001111b       ; mask out high nibble
    cmp al, 10
    sbb al, 69h
    das
    mov [edx + ecx], al     ; store the asciihex(AL) in the string
    shr esi, 4              ; next nibble
    dec cl                  ; decrease counter (one byte less than dec cl :-)
    jns @B                  ; eat them if there's any more
    pop esi
    ret
dw2hex endp
findNotZero proc uses ecx
    mov ecx, 8
@@:   
    mov al, byte ptr [esi]
    inc esi
    cmp al, '0'
    jnz @F
    dec cl
    jnz @B
@@:     
    dec esi
    ret
findNotZero endp   
; #########################################################################
Start:
    mov eax, -1
    mov ecx, 24
@@:   
    mov HexIn, eax
    push eax
    push ecx
    invoke dw2hex, HexIn, addr HexOut
    mov esi, offset HexOut
    call findNotZero
    invoke StdOut, esi
    invoke StdOut, addr CrLf
    pop ecx
    pop eax
    inc eax
    dec ecx
    jnz @B
    inkey
    exit
end Start



Regards herge
// Herge born  Brussels, Belgium May 22, 1907
// Died March 3, 1983
// Cartoonist of Tintin and Snowy