Problem converting string to bin/dec/hex
- From: spamtrap@xxxxxxxxxx
- Date: 13 Mar 2006 16:59:47 -0800
Hi Everyone,
I've already turned this in (and gotten a relatively poor grade for
my efforts), so this is no longer about me trying to get a good grade
for my assignment. I want to solve this problem.
=====
The Problem:
You are to write a 32-bit program when, when run, allows the user to
select from a menu:
1) Enter a Binary Number
2) Enter a Decimal Number
3) Enter a Hex Number
4) Quit
Once a number has been entered, it should be converted to the two
other formats and the application should print all three forms in the
output.
Requirements:
1. Print an intro statement w/ directions. Print this only once.
2. Display menu and prompt for selection.
3. Store number as entered by user in a variable so it may be
retrieved and converted by the program.
4. Divide tasks into manageable subroutines (PROC)
5. All output should go to the screen using proper formatting
techniques.
6. Program must accept binary numbers up to 32 bits long, 8-digit hex
values, and decimal values up to 4294967295. This will require DWORD
and 32b registers.
7. Check for input errors and print appropriate error messages.
8. Lowercase alpha numbers (in hex) should be converted to uppercase
before being printed in the output report.
9. Output should display all three forms of the number.
=====
OK ... I basically have everything working *except* the string->value
conversion. I'm absolutely stumped. My value->string conversion
(PrintNum) is working (and is quite elegant, IMO), but I'm stuck.
If anyone can point me in the right direction or is willing to put
together some code to solve my problem(s) in StrToBin, I'd be quite
grateful. This was written in ConTEXT and built using MASM 6.11.
GetChar, PutChar, GetString, and PrintString were all provided by my
instructor.
If you need kernel32.lib, it can be found here:
http://merlin.cs.uah.edu/labs/CS308/kernel32.lib
Thanks,
Chris
===== BEGIN SOURCE CODE =====
; Chris Brightwell
; CS308, Spring 2006
; Programming Assignment #2
; 07 March 2006
; DOS-Style 8.3 filename:
TITLE prog2.asm
; Setup some EQU values for later:
LF equ 0ah ;ASCII 10 - newline character
CR equ 0dh ;ASCII 13 - carriage return character
MAXSTR equ 256d ;Accept up to 256 characters
ENABLE_PROCESSED_INPUT equ 1 ;Flag to turn off line buffering
ENABLE_PROCESSED_OUTPUT equ 1 ;Flag to turn off line bufferin
ENABLE_LINE_WRAP equ 3 ;Flag to trun line wrap on
DISABLE_PROCESSED_INPUT equ 7 ;Flag to turn on line buffering
STD_INPUT equ -10d ;Function number for keyboard input
STD_OUTPUT equ -11d ;Function number for monitor output
; Setup our memory space:
..586
..MODEL FLAT
..STACK 4096h
;Include the kernel 32 library
INCLUDELIB kernel32.lib
;Prototype for attaching to console
SetConsoleMode PROTO NEAR32 stdcall,
hConsoleHandle:DWORD,
dwMode:DWORD
;Prototype for obtaining a file handle
GetStdHandle PROTO NEAR32 stdcall,
nStdHandle:DWORD
;Prototype for reading a file
ReadFile PROTO NEAR32 stdcall,
hFile:DWORD,
lpBuffer:NEAR32,
nNumberOfCharsToRead:DWORD,
lpNumberOfBytesRead:NEAR32,
lpOverlapped:NEAR32
;Prototype for writing a file
WriteFile PROTO NEAR32 stdcall,
hFile:DWORD,
lpBuffer:NEAR32,
nNumberOfCharsToWrite:DWORD,
lpNumberOfBytesWritten:NEAR32,
lpOverlapped:NEAR32
;Prototype for Exit of OS
ExitProcess PROTO NEAR32 stdcall,
dwExitCode:DWORD
; Begin Data Segment (DS)
..DATA
; Strings used throughout the application:
IntroStr BYTE LF,CR
BYTE 'This program allows you to enter a number (bin, hex, or
dec).'
BYTE LF,CR,'It will then convert that number to the other two
bases and '
BYTE LF,CR,'display the results.',0
MenuStr BYTE LF,LF,CR,'And your menu options are ...'
BYTE LF,CR,'1) Enter a Binary Number'
BYTE LF,CR,'2) Enter a Decimal Number'
BYTE LF,CR,'3) Enter a Hexadecimal Number'
BYTE LF,CR,'4) Quit',0
;These are used in conjunction with the menu logic
PromptStr BYTE LF,LF,CR,'Select a Menu Option: ',0
PromptBin BYTE LF,LF,CR,'Enter a binary value (less than 33
digits): ',0
PromptDec BYTE LF,LF,CR,'Enter a decimal value (less than
4294967295d): ',0
PromptHex BYTE LF,LF,CR,'Enter a hex value (less than 0xFFFFFFFFh):
',0
;Error strings
InputErrStr BYTE LF,CR,'*** Invalid input. Please try
again.',0
OverflowErrStr BYTE LF,CR,'*** ERROR: Input value is too
large.',0
IllegalCharErrStr BYTE LF,CR,'*** Illegal character: ',0
;Exit notice
ExitStr BYTE LF,CR,'Application exiting gracefully ... ',LF,LF,CR,0
;Test purposes only.
TestStr BYTE ' *TEST STRING* ',0
; These are used to build the output report
OutputStr1 BYTE LF,CR,'Input string was: ',0
OutputStr2 BYTE LF,CR,' As Bin: ',0
OutputStr3 BYTE LF,CR,' As Dec: ',0
OutputStr4 BYTE LF,CR,' As Hex: 0x',0
; Local variables for storing various data values.
InputChar BYTE 0h
InputAsStr DWORD 0h
InputValue DWORD 0h
CharTemp DWORD 0h
; These are used for kernel32 function calls:
strAddr DWORD ?
strLength DWORD ?
hStdOut DWORD ?
hStdIn DWORD ?
read DWORD ?
written DWORD ?
; End Data Segment (DS)
; Begin Code Segment (CS)
..CODE
_main:
lea esi, IntroStr ;Point to the intro string.
call PrintString ;Print it to the screen.
menu:
lea esi, MenuStr ;Point to the intro string.
call PrintString ;Print it to the screen.
prompt:
lea esi, PromptStr ;Point to the intro string.
call PrintString ;Print it to the screen.
lea esi, InputChar ;Storage location for input char
call GetChar ;Get input char from keyboard
processInput:
cmp InputChar, '1' ;Compare input to '1'
je binPrompt ;Jump if equal
cmp InputChar, '2' ;Compare input to '2'
je decPrompt ;Jump if equal
cmp InputChar, '3' ;Compare input to '3'
je hexPrompt ;Jump if equal
cmp InputChar, '4' ;Compare input to '4'
je exit ;Jump if equal
;If you get here, there was no valid input.
lea esi, InputErrStr ;Point to the error msg
call PrintString ;Print the error msg
jmp prompt ;Jump back to the input prompt
binPrompt:
lea esi, PromptBin ;Point to the binary input
prompt
call PrintString ;Print the prompt
lea esi, InputAsStr ;Point to a variable to store
input
call GetString ;Get input from the keyboard.
lea esi, InputAsStr
call StrToBin
call PrintOutput
jmp menu
decPrompt:
lea esi, PromptDec ;Point to the decimal input
prompt
call PrintString ;Print the prompt
lea esi, InputAsStr ;Point to a variable to store
input
call GetString ;Get input from the keyboard.
lea esi, InputAsStr
call StrToDec
call PrintOutput
jmp menu
hexPrompt:
lea esi, PromptHex ;Point to the hex input prompt
call PrintString ;Print the prompt
lea esi, InputAsStr ;Point to a variable to store
input
call GetString ;Get input from the keyboard.
lea esi, InputAsStr
call StrToHex
call PrintOutput
jmp menu
exit:
lea esi, ExitStr ;Point to the exit message
call PrintString ;Print the exit message
INVOKE ExitProcess, 0 ;Exit with return code 0
;StrToBin Procedure - Converts Str input to unsigned Bin value
;Given: Null-terminated string in DS:InputAsString
;Returns: unsigned value in DS:InputValue
StrToBin PROC NEAR32
pushad ;save registers
pushfd ;save flags
mov strAddr, esi ;store string address
mov strLength, 0h ;zero the counter
ReadChar:
cmp BYTE PTR [esi], 0 ;char = null?
jz EndReadChar ;if so, you're done
cmp BYTE PTR [esi], ' ' ;char = whitespace?
jz NextChar ;if so, skip it.
PushChar:
mov eax, [esi] ;copy char to register
add eax, 30h ;conver to int
push eax ;push it onto the stack
inc strLength ;increment counter
NextChar:
inc esi ;increment the pointer
jmp ReadChar ;jump back to the top of the
loop
EndReadChar:
mov ebx, 1d ;setup ebx for multiplication
BuildValue:
cmp strLength, 0 ;strLength = 0?
jz EndBuildValue ;if so, you're done
pop eax ;pop an int off the stack
mul ebx ;multiply by ebx
add InputValue, eax ;add it to the accumulator
;increment ebx (2^0, 2^1, 2^2, 2^3, ... , 2^32)
mov eax, ebx ;mov current multiplier to eax
mov ebx, 2d ;setup 2x multiplier in ebx
mul ebx ;multiply!
mov ebx, eax ;move multiplier back to ebx
dec strLength ;decrement the counter
jmp BuildValue ;jump back to top of loop
EndBuildValue:
popfd ;restore flags
popad ;restore registers
ret
StrToBin ENDP
;StrToDec Procedure - Converts Str input to unsigned Dec value
;Given: Null-terminated string in DS:InputAsString
;Returns: unsigned value in DS:InputValue
StrToDec PROC NEAR32
pushad ;save registers
pushfd ;save flags
popfd ;restore flags
popad ;restore registers
ret
StrToDec ENDP
;StrToHex Procedure - Converts Str input to unsigned Hex value
;Given: Null-terminated string in DS:InputAsString
;Returns: unsigned value in DS:InputValue
StrToHex PROC NEAR32
pushad ;save registers
pushfd ;save flags
popfd ;restore flags
popad ;restore registers
ret
StrToHex ENDP
;PrintNum Procuedre - Prints a number M in base N
;Given: unsigned 32-bit value in EAX, radix in EBX
;Returns: Nothing
PrintNum PROC NEAR32
start:
pushad ;save registers
pushfd ;save flags
mov ecx, 0d ;zero ecx to use for counter
build:
xor edx,edx ;zero edx for division
div ebx ;div abx/ebx, store remainder is
in edx
push edx ;push remainder onto stack
inc cx ;incrememnt our counter
cmp eax, 0h ;is the value in eax > 0?
jnle build ;if so, keep dividing
print:
pop eax ;pop a number off the stack
cmp eax, 9d ;eax >= 9d ?
jnle printLetter ;if so, print as hex
printDigit:
add eax,30h ;conver num to char
jmp continue ;continue
printLetter:
add eax,37h ;conver num to char
jmp continue ;continue
continue:
mov CharTemp,eax ;store char in variable
lea esi,CharTemp ;point to variable for printing
call PutChar ;print char w/ PutChar
dec cx ;decrement the counter
cmp cx, 0h ;is the value in cx > 0?
jnle print ;if so, keep printing
return:
popfd ;restore flags
popad ;restore register
ret
PrintNum ENDP
;PrintOutput Procedure - Prints output block
;Given: Values in DS
;Returns: Nothing
PrintOutput PROC NEAR32
;Print original input string
lea esi, OutputStr1 ;point to string variable
call PrintString ;print it
lea esi, InputAsStr ;point to another string var
call PrintString ;print it, too
; **** TEST VALUE ONLY ***
;mov InputValue, 255d ;***
; **** TEST VALUE ONLY ***
;Print input as binary value
lea esi, OutputStr2 ;point to string var
call PrintString ;print it
mov eax, InputValue ;point to InputValue (hex)
mov ebx, 2d ;mov radix (2 for bin) to EBX
call PrintNum ;call the printnum procedure
;Print input as decimal value
lea esi, OutputStr3
call PrintString
mov eax, InputValue ;mov InputValue (hex) to EAX
mov ebx, 10d ;mov radix (10 for dec) to EBX
call PrintNum
;Print input as hex value
lea esi, OutputStr4 ;point to string var
call PrintString ;print it
mov eax, InputValue ;mov InputValue (hex) to EAX
mov ebx, 16d ;mov radix (16 for hex) to EBX
call PrintNum
;return to calling procedure
ret
PrintOutput ENDP
;********************* Near procedure to get a Character
**********************
; Given : The Address of the Character to get in ESI register
; Process : Input the Character using the kernel32.lib ReadFile from
the
; : Standard_Input function call. No registers are changed
and the
; : flags are not affected.
; Return : The input character in the data segment
;******************************************************************************
GetChar PROC NEAR32 ; Define procedure
pushad ; save all registers
pushfd ; save flags
INVOKE GetStdHandle,STD_INPUT ; get handle for keyboard
mov hStdIn, eax ; save the handle
INVOKE SetConsoleMode, ; invoke standard console
with
hStdIn, ; file handle for
keyboard
ENABLE_PROCESSED_INPUT ; turn line buffering off
INVOKE ReadFile, ; invoke standard ReadFile
with
hStdIn, ; file handle for
keyboard
esi, ; address of character
1, ; length of one byte
NEAR32 PTR read, ; variable for # bytes
read
0 ; overlapped mode
call PutChar ; echo the character on
screen
popfd ; restore flags
popad ; restore registers
ret ; return to caller
GetChar ENDP
;******************* NEAR32 procedure to print a Character
********************
; Given : The Address of the Character to print in ESI register
; Process : Print the Character using the kernel32.lib WriteFile to
; : Standard_Output function call. No registers are changed
and the
; : flags are not affected.
; Return : Nothing
;******************************************************************************
PutChar PROC NEAR32
pushad ;save registers
pushfd ;save flags
INVOKE GetStdHandle, ;get a handle
STD_OUTPUT ;for console output
mov hStdOut, eax ;copy file handle for screen
INVOKE SetConsoleMode, ;invoke standard console with
hStdOut, ; file handle for screen
ENABLE_PROCESSED_OUTPUT ; turn line buffering off
INVOKE WriteFile, ;invoke standard WriteFile with
hStdOut, ; file handle for screen
esi, ; address of character
1, ; length of one byte
NEAR32 PTR written, ; variable for # bytes written
0 ; overlapped mode
popfd ;restore flags
popad ;restore registers
ret ;return to caller
PutChar ENDP
;********************* Near procedure to get a String
*************************
; Given : The Address of the String to fill in ESI register
; Process : Input the String using the kernel32.lib ReadFile from the
; : Standard_Input function call. No registers are changed
and the
; : flags are not affected.
; Return : The input string in the data segment
;******************************************************************************
GetString PROC NEAR32 ; Define procedure
pushad ; save all registers
pushfd ; save flags
INVOKE GetStdHandle,STD_OUTPUT ; get handle for console
mov hStdOut, eax ; save the handle
INVOKE SetConsoleMode, ; invoke standard console
with
hStdOut, ; file handle for
keyboard
ENABLE_LINE_WRAP ; turn line wrap on
INVOKE GetStdHandle,STD_INPUT ; get handle for console
mov hStdIn, eax ; save the handle
INVOKE SetConsoleMode, ; invoke standard console with
hStdIn, ; file handle for keyboard
DISABLE_PROCESSED_INPUT ; turn line buffering on
mov ecx, MAXSTR ; string length
mov strLength, ecx ; maximum string to accept
mov strAddr, esi ; save pointer to input string
INVOKE ReadFile, ; invoke standard ReadFile with
hStdIn, ; file handle for keyboard
strAddr, ; address of string
strLength, ; length of string
NEAR32 PTR read, ; variable for # bytes read
0 ; overlapped mode
mov ecx, read ; number of bytes read
mov BYTE PTR [esi+ecx-2],0 ; replace CR/LF by trailing null
popfd ; restore flags
popad ; restore registers
ret ; return to caller
GetString ENDP
;******************* NEAR32 procedure to print a string
***********************
; Given : The Address of Null (0) terminated String to print in ESI
register
; Process : Print the String using the kernel32.lib WriteFile to
; Standard_Output function call. No registers are changed
and the
; flags are not affected.
; Return : Nothing
;******************************************************************************
PrintString PROC NEAR32
pushad ; save registers
pushfd ; save flags
mov strAddr, esi ; copy string address
; find string length
mov strLength, 0 ; initialize string length
WhileChar: cmp BYTE PTR [esi], 0 ; character = null?
jz EndWhileChar ; exit if so
inc strLength ; increment character count
inc esi ; point at next character
jmp WhileChar ; while more characters exist
EndWhileChar:
INVOKE GetStdHandle,STD_OUTPUT ; get handle for console
output
mov hStdOut, eax ; copy file handle for screen
INVOKE WriteFile, ; invoke standard WriteFile with
hStdOut, ; file handle for screen
strAddr, ; address of string
strLength, ; length of string
NEAR32 PTR written, ; variable for # bytes written
0 ; overlapped mode
popfd ; restore flags
popad ; restore registers
ret ; return to caller
PrintString ENDP
; End Code Segment (CS)
Public _main
END
===== END SOURCE CODE =====
.
- Follow-Ups:
- Re: Problem converting string to bin/dec/hex
- From: Mark Whitlock
- Re: Problem converting string to bin/dec/hex
- From: Grumble
- Re: Problem converting string to bin/dec/hex
- From: Frank Kotler
- Re: Problem converting string to bin/dec/hex
- Prev by Date: Re: Programming GPU with ASM
- Next by Date: Re: How does prefetchnta minimize cache pollution?
- Previous by thread: Re: Programming GPU with ASM
- Next by thread: Re: Problem converting string to bin/dec/hex
- Index(es):
Relevant Pages
|