Hey again everyone, it's been a while since I've posted here.. What I'm trying to do, is get the command-line argument and convert it to hexidecimal. Example, if the file is named 'test', you would call it with

test 72

Or something similar.
I have it working, but after MUCH examining what the shl\shr instructions do to Binary values, and what it ends up with in Hex, I have found that it converts the value '72' into 7020 (So, this displays the colors correctly.. but only sets it to the first two digits, 70.. so I end up with a white background\black text)

What I was thinking as a solution, was to somehow trap JUST the 4 binary digits.. From what I see, this would be called a Nybble?

Example.. 00110010 binary = 32 hexidecimal, when it gets shifted into AH it turns into
00100000 (20), while it should be a 2. A solution would be to pull out JUST the first 4 bits, '0010' which would be a 2, maybe then I could add those two to the same byte position and it would make one hexidecimal value.

However.. When trying this for my first time...
mov byte [store + 0],ah
lodsb
add byte [store + 0],ah

With 72 as the argument.. it became a 90? Which is a blue background, black text. (I see why, 7 + 2 = 9).. But, Is it possible to do 70 + 2 = 72?

I am on a Windows OS and assembling with NASM16

I know, this program is a little sloppy, but I'm just using it as a 'test' for my other program "Linecol".. Look at it on Youtube if you have the time please, my username is Goalatio.

Here's my code, the library that I am using will be below the code.

Also.. I'd like to thank "NotNull" for all of the help he has supplied me, you have really gotten me into Assembly language.. and much of what I know would not have been possible had you not showed me a few simple commands.

[org 0100h]
%include "Library.asm"

[section .text]
arg			;Get arguments
write			;Display arguments
mov si,bx		;Put arguments into SI
lodsb			;Advance one position
shl ax,12		;Shift ax left 12 times to get AL into AH
mov byte [store + 0],ah	;Place the attribute into first spot of storage

xor ax,ax		;Zero-out AX
lodsb			;Advance once more
shl ax,12		;Shift ax left 12 times to get AL into AH
mov byte [store + 1],ah	;Place this in the second part of the storage
color 80,[store],0	;Use library to display a colored line with new colors
string hello		;Use library to display "Hello"




EXIT:
exit 0			;Exit with ERRORLEVEL of 0

[section .data]
store times 2 db 0		;Where color attributes are store
hello db "Hello", 13, 10, "$"	;The test message

And the library it needs...

;===========================================
;string - displays the string passed as an argument
;===========================================
%macro string 1
xor dx,dx
xor ah,ah
mov dx,%1		;Move the passed string into DX
mov ah,9		;Function 09h, display string
int 21h			;Call DOS

%endmacro
;===========================================



;===========================================
;exit - exits with passed errorlevel
;===========================================
%macro exit 1
mov  AH,4CH		;Terminate process DOS service
mov  AL,%1		;Pass this value back to ERRORLEVEL
int  21H		;Call DOS to exit

%endmacro


;===========================================
;arg - Gets the argument and passes it to DX
;===========================================
%macro arg 0
xor bx, bx 		;Zero out BX
mov bl, [cs:0x80]	;Get Command Tail Length
mov byte [bx+0x81],'$'	;Place a $ on command tail
mov bx, 0x82		;place offset of command tail in BX.
mov dx,bx		;Move offset into DX

%endmacro

;===========================================
;write - writes the string passed into DX
;Caller must pass:
;String or value into DX
;===========================================
%macro write 0
mov ah,9		;Function 9, display string
int 21h			;Call DOS to display it

%endmacro


;===========================================
;color - sets color while printing characters
;params:
;1: Amount of times to repeat
;2: HEXIDECIMAL color value
;3: Character to print
;===========================================


%macro color 3
mov cx,%1 		;CX value = amount of chars to print
mov bl,%2		;BL value = HEXI color attr
mov al,%3		;AL value = character to print
mov ah,9		;Function 9, display char
int 10h			;Call the SCREEN vector

%endmacro

And.. my "Quick-compilation" batch file.. You are free to keep any of this code for your own use\learning purpose if you like.

@echo off
:Start
cls
set fn=Test
nasm16 %fn%.asm -o %fn%.com
echo.
%fn% 72
echo.
echo Errorlevel return value: %errorlevel%
pause>nul

Recommended Answers

All 7 Replies

So your getting a hexadecimal value from the command
line in the form of asci characters???
Couldn't tell exactly what your code was doing.

Heres an example, the asci string '72' is specified as a
command line parameter, it makes the asci-values
37h and 32h.
So why not create an array such as this to get the
value of each nibble:

arr db '0123456789ABCDEF'
start:
mov al, '7' ; ASCI val 37h
mov di, arr
mov cx, 0x10
repnz scasb
dec di
sub di, arr ; DI==7

When you get what is supposed to be the high-nibble
bit shift it to the left by four bits, so 07 becomes 70.
Then when you get the low-nibble '2' add it to 70+2=72h

What I am trying to do is allow them to enter the colors of the line in hexadecimal.

Ex;
Test 64

Would set the background color to 6 (yellow) and text to 4 (red). But, it sets the values for that as
6040, and only takes the 60 as a hexadecimal number.. (Ends up only setting the background color to yellow, then uses that 0 to set text color to black).

May seem like an odd question to ask, but do you have an MSN account? Would be easier than posting here, because I do not always have my email (as a notification that someone has posted) open.

If you are interested.. my MSN is Goalatio@live.com

Ok, well I made code that accepts a hexadecimal number
at the command line and prints an 'A' with the specified
background/foreground colors.

bits 16
org 100h

start:
mov cx, 2
mov si, 0x82
mov di, hexnum
cld
rep movsb
mov al, byte [hexnum]
call getnibble
shl al, 4
push ax
mov al, byte [hexnum+1]
call getnibble
pop bx
add bl, al
mov al, 0x41
mov cx, 1
xor bh, bh
mov ah, 0x9
int 0x10
int 0x20

getnibble:
mov di, hexdig
mov cx, 0x10
repnz scasb
dec di
sub di, hexdig
mov ax, di
ret

hexnum db 0,0
hexdig db '0123456789ABCDEF'

Sorry, i've been gone for a while.

Anyways, what do the commands..
rep movsb (Repeat mov-string-byte)?
repnz scasb (Repeat not zero 'store ...? string-byte')
I've never seen those two commands, would you mind saying what they do?

I changed my code around a bit so that it doesn't need the library anymore. Do you see what I did wrong? It still only gives me
6040 when I use 64 as an argument, or 7020 if I use 72..
Then to prove that it does this, I made it display its ASCII rep.
7020 = p.. because the 70 is a p.

[org 0100h]

[section .text]

;Get arguments from CMD
xor bx, bx 		;Zero out BX
mov bl, [cs:0x80]	;Get Command Tail Length
mov byte [bx+0x81],'$'	;Place a $ on command tail
mov bx, 0x82		;place offset of command tail in BX.
mov dx,bx		;Move offset into DX

mov si,bx		;Put arguments into SI

lodsb			;Advance one position in SI
shl ax,12		;Shift ax left 12 times to get AL into AH
mov byte [store + 0],ah	;Place the attribute into first spot of storage

xor ax,ax		;Zero-out AX
lodsb			;Advance once more
shl ax,12		;Shift ax left 12 times to get AL into AH
mov byte [store + 1],ah	;Place this in the second part of the storage

;Display colored line
mov cx,80 		;Says to display 80 characters (One CMD line)
mov bl,[store]		;Display the collected color attribute
mov al,0		;Display 0... blank space
mov ah,9		;Function 9x10 - Display character with attribute
int 10h			;Call the BIOS

mov ah,9		;Function 9x21 - Display string
mov dx,hello		;Load string into DX (Hello)
int 21h			;Display it

mov byte [store + 2], '$'	;Put a string terminator onto the color storage
mov ah,9		;Function 9x21 - Display string
mov dx,store		;Load color storage into DX
			;To display its ASCII rep.
int 21h			;Display it




EXIT:
mov ah,4ch		;Function 4CHx21 - Exit with ERRORLEVEL
mov al,0		;Set ERRORLEVEL to 0
int 21h			;Exit

[section .data]
store times 3 db 0		;Where color attributes are stored
hello db "Hello", 13, 10, "$"	;The test message

15. shl ax, 12
actually a byte is 8-bits so shl ax, 8 to get AL into AH
16. mov byte [store + 0],ah
You are storing the hex digits into two separate bytes, the attributes
are actually contained in the low and high nibble of one byte.
So:

mov al, firsthexdigit
shl al, 4 ; place first digit in high nibble of byte
add al, secondhexdigit ; place second digit in low nibble

You are also moving this byte from the command tail without translating it into a value instead of an ASCII value. so 39h ('9')
should become 9.
25. mov bl,[store] ; reads one byte from 'store'
you stored attributes at store+0 store+1
example:
mov bl, 9fh ; light-blue background/bright-white foreground

On the MOVSB and SCASB instructions.
SCASB compares the byte in AL to the byte at ES : DI,
it subtracts the two bytes from each other to update FLAGS
just like the CMP instruction, so things like JZ and REPNZ can
be used.
SCASB increments or decrements DI according to the value of
the direction flag (DF).
MOVSB moves the byte at DS : SI to ES : DI and increments or
decrements SI and DI according to the value of the
direction flag (DF).
There are several string movement and string comparison instructions,
the direction flag is set and cleared by STD and CLD instructions.
When DF=0 addresses are incremented, otherwise decremented.

Thanks for that last comment (Eventually got it to work exactly how I wanted it to.)

Finished code:

[org 0100h]

[section .text]

;Get arguments from CMD
xor bx, bx 		;Zero out BX
mov bl, 0x80		;Get Command Tail Length at address 0x80
mov bx, 0x82		;place offset of command tail into BX.
mov dx,bx		;Move offset into DX

mov si,bx		;Put arguments into SI

xor ax,ax
lodsb			;Advance one position in SI
shl al,4		;Shift AL left 4 times *Moves number value into tens column*
mov [store1],al		;Store this value into store1
xor ax,ax		;Zero-out AX
lodsb			;Advance once more
shl al,4		;Shift AL left 4 times to delete tens column *SECOND HEX ATTRIBUTE*
shr al,4		;Shift it right 4 times so that the entire left side = "0000" and right-side keeps the entered value
mov [store2],al		;Store this in a variable
xor al,al		;Clear AX to 0
mov al,[store1]		;Mov the first hex value into AL
add al,[store2]		;Add the second one that it AL looks like this. "1st value:2nd value"
mov [store],al		;Place AL into a final variable


;Display colored line
mov cx,80 		;Says to display 80 characters (One CMD line)
mov bl,[store]		;Display the collected color attribute
mov al,0		;Display 0... blank space
mov ah,9		;Function 9x10 - Display character with attribute
int 10h			;Call the BIOS

mov ah,9		;Function 9x21 - Display string
mov dx,hello		;Load string into DX (Hello)
int 21h			;Display it




EXIT:
mov ah,4ch		;Function 4CHx21 - Exit with ERRORLEVEL
mov al,0		;Set ERRORLEVEL to 0
int 21h			;Exit

[section .data]
store db 0		;Where color attributes are stored
hello db "Hello", 13, 10, "$"	;The test message
store1 db 0
store2 db 0

And now I added the full functionality of my old linecol command.
linecol "attr" "text"

Again, thanks for the help.

[org 0100h]

[section .text]

;Get arguments from CMD
xor bx, bx 		;Zero out BX
mov bl, 0x80		;Get Command Tail Length at address 0x80
mov bx, 0x82		;place offset of command tail into BX.
mov dx,bx		;Move offset into DX

mov si,bx		;Put arguments into SI

lodsb			;Advance once to check for the first quote (")
cmp al, '"'		;Check for quote
je GETATTR		;If it's there, we can continue
jmp ERRORCALL		;If not, flag an error

;====================================
;GETATTR - Gets the color attributes
;====================================
GETATTR:
xor ax,ax
lodsb			;Advance one position in SI

cmp al, '"'		;Check if it's a quote
je ERRORCALL		;If it is, flag an error

shl al,4		;Shift AL left 4 times *Moves number value into tens column*
mov [store1],al		;Store this value into store1
xor ax,ax		;Zero-out AX
lodsb			;Advance once more

cmp al, '"'		;Check if it's a quote
je ERRORCALL		;If it is, flag an error

shl al,4		;Shift AL left 4 times to delete tens column *SECOND HEX ATTRIBUTE*
shr al,4		;Shift it right 4 times so that the entire left side = "0000" and right-side keeps the entered value
mov [store2],al		;Store this in a variable
xor al,al		;Clear AX to 0
mov al,[store1]		;Mov the first hex value into AL
add al,[store2]		;Add the second one that it AL looks like this. "1st value:2nd value"
mov [store],al		;Place AL into a final variable

lodsb			;Advance once more to check for an ending quote
cmp al, '"'		;Check if it's a quote
je GETTEXT		;If it is, go and get the text
jmp ERRORCALL


;====================================
;GETTEXT - Starts GETTEXTLOOP and sets it up
;====================================
GETTEXT:
lodsb			;Advance once more into SI
cmp al, ' '		;Check for a space
jne ERRORCALL		;If it's not there, flag an error

lodsb			;Advance to check for a quote
cmp al, '"'		;Check for quote
jne ERRORCALL		;If not there, flag an error
xor bx,bx		;Set BX to 0 to start a counter
mov byte [arguments + 80], '$'	;Put string terminator into last position of array so it can be displayed

;--
;GETTEXTLOOP - Gets the text arguments
;--
GETTEXTLOOP:
cmp bx,80		;Check if buffer is full
je OVERFLOWTEXT		;Flag an overflow if it is

lodsb			;Advance into SI to get characters

cmp al,'"'		;Check for final quote
je DRAWLINE		;If it's there, draw the line + text

mov [arguments + bx],al	;Store character into current array position
inc bx			;Increase array counter
jmp GETTEXTLOOP		;Loop

;====================================


;====================================
;DRAWLINE - Displays all of the collected color and text data
;====================================
DRAWLINE:
;Display colored line
mov cx,80 		;Says to display 80 characters (One CMD line)
mov bl,[store]		;Display the collected color attribute
mov al,0		;Display 0... blank space
mov ah,9		;Function 9x10 - Display character with attribute
int 10h			;Call the BIOS

mov dx,arguments	;Load string into DX (Text to display)
call WRITE		;Display it
jmp EXIT

OVERFLOWTEXT:
mov dx,overflow1
call WRITE
jmp EXIT


EXIT:
mov ah,4ch		;Function 4CHx21 - Exit with ERRORLEVEL
mov al,0		;Set ERRORLEVEL to 0
int 21h			;Exit



ERRORCALL:
mov dx,errormsg		;Load error message into DX
call WRITE		;Display it
call EXIT		;Exit

WRITE:			;Writes text in DX
mov ah,9		;Function 9x21 - Display string
int 21h			;Call DOS
ret

[section .data]
store db 0		;Where color attributes are stored
arguments times 80 db 0
store1 db 0
store2 db 0
overflow1 db "Overflow in section 'Text', you may only use 79 characters.", 13, 10, "$"
errormsg db 'Invalid syntax.  Use [linecol "attribute" "text"].', 13, 10, "$"
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.