Public Group

# coding fun with MASM

This topic is 4414 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

hey I picked up a book on assembly code with masm and am trying to get the knack of this stuff.... i just want to output a binary digit. i can figure out how to do it with a hex number, but the binary's got me all sorts of confused. here i my code for the hex output
	DOSSEG
.MODEL	small
.STACK	100h

.DATA
cr	EQU	0Dh
lf	EQU	0Ah

digit_table	DB	'0123456789ABCDEF'
hex_str	DB	'0000h', cr, lf, '\$'
divisor	DW	16

number	DW	0F8D2h

.CODE
start:
.STARTUP

;---------------------------------------------------
; copy the number to AX so it doesn't get clobbered.
; As we loop AX will contain the high bits yet to be converted to hex
; digits.
;---------------------------------------------------
mov	ax,	number

;---------------------------------------------------
; I'm using DI to index the converted hex string as an array
; starting with index 3 (the 4th hex char) and working my
; way back to index 0 (the 1st hex char).  I have to use DI because
; memory indexing (like the "mov [di], al" instruction) requires
; an index register as the first operand
;---------------------------------------------------
mov	di,	OFFSET hex_str	; Get the memory address of the hex
; string I am filling.

mov	cx,	4		; Do the following loop 4 times... CX
; is like the "i" of

;---------------------------------------------------
; while (cx != 0)								;---------------------------------------------------
hex_loop:
cmp	cx,	0			; Compare CX to zero.

; Division requires a 32-bit dividend and a 16 bit divisor.  Since our
; registers are only 16 bits, the "div" instruction fakes a 32 bit
; number by assuming the dividend's high 16 bits are in DX and low 16
; bits in AX.  The number we're working on is already in AX and is only
; 16 bits, but since the instruction requires 32 bits we zero out DX so
; the value of the number isn't affected.  After the division
; instruction completes the quotient is in AX and the remainder in DX.
; Dividing our number by 16 gives a remainder that is the lowest order
; nibble we're tunring to a hex digit and a quotient that represents
; the rest of the number left to convert.
;---------------------------------------------------
mov	dx,	0	; Zero out the high 16 bits of the DX:AX
div	divisor		; Divide (unsigned) the number by 16
push	ax		; The "xlat" instruction below requires the use
; of AL so we must save our quotient
;---------------------------------------------------
mov	bx,	OFFSET digit_table	; Get the address of
; the "digit_table".  "xlat"
; expects this address in BX.
mov 	al,	dl		        ; AL needs to indicate
; to "xlat" which position of
; the array to index.
xlat					; Grab the hex digit indexed by
; BX[AL] and store it in AL

mov	[di],	al			; Store the hex digit in
; the "di"th position of our
; output string

pop	ax				; Get our quotient back from
; the stack

sub	di,	1			; "di--" shifts our string
; index BACK a byte to prepare
; for the next loop iteration

sub	cx,	1			; Decrement our loop index

jmp	hex_loop			; Jump back to the top of
; our "while" loop.
end_hex_loop:

;---------------------------------------------------
; Print our hex string to the screen using the PROCEDURE
; we developed in class
;---------------------------------------------------
mov 	ax,	OFFSET hex_str
call	disp_str

.EXIT

;---------------------------------------
; disp_str : Display string of bytes using
;            DOS int 21h, function 09h
; INPUT : AX should contain the address of
;         the string of bytes
;---------------------------------------
disp_str	PROC
push	ax
push	dx

mov	dx,	ax
mov	ah,	09h
int	21h

pop	dx
pop	ax

ret
disp_str	ENDP


i think its easier to work with hex numbers than with binary...

##### Share on other sites
It's far easier to work with binary than with hex. The processor works using a binary logic, so you just need to use the simple way.

The basic instructions you need are:
* shl (left shift by one bit)
* jc (jump if carry)
If you want to avoid any jumps, you can use adc:
  mov    eax, my_number ; your number is in eax  mov    ecx, 32        ; loop count is in ecxthe_loop:  xor    ebx, ebx       ; set ebx to 0  shl    eax, 1         ; left shift eax by one                        ; if the MSB is 1, the carry                         ; flag will be set  adc    ebx, 0         ; ebx = ebx + 0 + carry flag; Now ebx contains either 1 or 0, depending on the MSB of eax; you can print it using a print routine; note that if you replace the constant with the value of the '0' char,; you directly get the character you'll want to display  loop   the_loop       ; ecx--, then loop to "the_loop" only if ecx != 0

That's all.

Of course, this routine is very specialized - it also don't take the output to a string into account (but this can be solved rather easily).

As you see, it is far easier than the hex version [smile]

HTH,

1. 1
2. 2
Rutin
19
3. 3
khawk
18
4. 4
5. 5
A4L
11

• 9
• 12
• 16
• 26
• 10
• ### Forum Statistics

• Total Topics
633768
• Total Posts
3013753
×