RA equ this byte
R0 byte 0
R1 byte 0
R2 byte 0
R3 byte 0
R4 byte 0
R5 byte 0
memory byte 1024 dup(0)
rip word 0
Is the address the MSB (most significant byte: bits 8-15) and the value the LSB (least significant byte: 0-7), or is the entire 16 bits used for the address, and then I just assign the size for its values... somehow? I'm confused, grr.
mov al, byte ptr memory[esi]
bit: smallest unit on binary computer, each digit in binary is a bit
nibble: 4 bits (same as a hexidecimal digit), (2 nibbles = 1 byte)
byte: 8 bits (2 nibbles/hexidecimal digits), smallest addressable unit on most computers
word: 16 bits (2 bytes)
dword (double word): 32 bits (4 bytes)
qword (quad word): 64 bits (8 bytes)
---------------------------
for the most part (at least what we're learning), there's really no difference between the 32 bit that we're learning and the old 8086 (80x86) that you are used to Jay, we're mostly learning how to do the same stuff you'd do on/with the 8086, with the only difference is in that we use 32 bit registers (except the segment registers, they stay 16 bit):
80386 (.386):
eax = (16 bit extended ax) = 32 bits (31 bit to 0 bit)
eax:
ax = lower/lsb of eax, 16 bits (15 bit to 0 bit)
N/A = we can't refer/index into the higher/msb of eax, 16 bits (bit 31 to bit 16)
ax:
ah = higher/msb of ax, 8 bits (bit 15 to bit 8)
al = lower/lsb of ax, 8 bits (bit 7 to bit 0)
VS
8086 (80x86):
ax = 16 bits (15 bit to 0 bit)
ax:
ah = higher/msb of ax, 8 bits (bit 15 to bit 8)
al = lower/lsb of ax, 8 bits (bit 7 to bit 0)
-----------------
so you can just explain to me or help me in term of the 8086, as I don't think there'll be much difference or confusion on my part, due to not really doing anything different in the 32 bit cpu system of registers of 80386. You don't need to try to learn the 80386 as it really seems to behave and/or be designed in the same way as the 8086 design/build
I'm guessing that the '1024' byte array variable 'program_buffer byte 1024 dup (?/0)', since it *IS* being used to hold the read data from the 'machine.bin' file that we're using to test our program, would be used for the 'reseting to location 0', and not my own written MASM program's DS and/or CS, does this sound right, or completely wrong?
Then, using the address location of my '6' byte array variable 'RA byte 6 dup (?/0)', I can index/scale/direct-offset (via as adjusting "ip") to the specific sub-segment (R0-R5: virtual/emulation/substitute registers) of it. And, if I understand correctly, I can make the address size of it be 16 bits by another means (such as maybe the 'word ptr' or something to that effect, which I would need to be 16 bits in order to do the indexing/scaling/etc to the subsegment R0-R5 "registers", anyways, right?)
Are then the given instruction set's opcodes, refering to the memory addresses in the 1024 byte array variable (via adjusting "ip") ?? Or, am I to create the instruction sets in my own program, refering to them via the DS (if they're to be variables) and/or the CS as (if they're to be) Labels/Procedures/Macros?
get next byte pointed to by IP
increment IP
store that value in the A register
get next byte pointed to by IP and hold it somewhere
increment IP
get next byte pointed to by IP
increment IP
combine the two bytes into an address
get the byte pointed to by that address
store that value in the A register.
CPU contains 6 registers each 8 bits (R0 – R5 valued 0 – 5)
does this mean that the registers are initially set to having those values?:
Or, am I getting confused, and I just iterate through the mem array
05 -> R5 // well, this actually can't be done, lol, as 05 is already an opcode... lol
so far in the 'machine.bin' the register offset has been 0 or 1 (meaning we're just using storing/loading the value from/into the msb/lsb of the address)
05 04 01 A3
LOAD R4, value at address*
*does this mean just '01 h' (1 d) or '01A3 h' (419 d/t) or '0xA301 h' (41729 d/t) ???
I can do this? for example:
mov RA[0], dl/dh
but.. which do I use? the low or high? don't I need both low and high, as isn't that the value I want to store? I'm still a bit confused with this...
Pre_start:
xor ebx, ebx ;this is what I use for the incrementing index
mov ecx, LENGTHOF program_buffer
;I just read that the 'loop' has a limited range, so to be safe, am using manual decrement ecx checking-jump, though hopefully I don't have the same issue ;with the jumping (near vs far), as I've not tried to understand them, lol.
Start:
sub ecx, 01h
;used for the looping, do I need to use 'sbb' (subtract with barrow/carry?), as I don't understand carry arithmetic or nor bit carrying in general
cmp program_buffer[ebx], LOAD ;LOAD EQU 05h
je Load
cmp program_buffer[ebx], Store ;STORE EQU 06h
je Store
cmp program_buffer[ebx], ADD_ENUM ;ADD_ENUM EQU 11h
;ADD (and others) got color coded... so I'm using 'ADD_ENUM' just to be safe, as I don't want to over-write an instruction set operation, lol
je Add_Enum
cmp program_buffer[ebx], SUB_ENUM ;SUB_ENUM EQU 22h
je Sub_Enum
cmp program_buffer[ebx], XOR_ENUM ;XOR_ENUM EQU 44h
je Xor_Enum
cmp program_buffer[ebx], LOAD_R ;LOAD_R EQU 55h
je Load_R
cmp program_buffer[ebx], STORE_R ;STORE_R EQU 66h
je Store_R
cmp program_buffer[ebx], JNZ_ENUM ;JNZ_ENUM EQU 0AAh
je Jnz_Enum
cmp program_buffer[ebx], OUT_ENUM ;OUT_ENUM EQU 0CCh
je Out_Enum
cmp program_buffer[ebx], HALT ;HALT EQU 0FFh
je Halt
cmp ecx, 00h ;or it's: 01h
;need to figure it out (confused where/when ecx is needed to be checked at: 0 or 1), easy to test it, when I get to it...
je Finish
add ebx, 01h ;just in case a value doesn't match up with any of the compares, to advance it to the next value (next address)
jne Start
Load:
add ebx, 01h ;moves index from opcode address/value (05) to register address/value (04)
movzx eax, program_buffer[ebx] ;the 'movzx' fills in zeroes for the rest (unused) of the bit slots ;storing the register index into eax
add ebx, 01h ;moves index from register address/value (04) to the left byte of the address' address/value (01 of 01,A3)
movzx edx word ptr program_buffer[ebx]
;the 'type:word ptr' gets (in this case) 01A3 for us and puts it into edx (and movzx zeroes the remaining unused bits), which I think you do differently in your 8085/8086 code
xchg dh, dl ;this should switch the high and low bits (big endian to little endian), so now dx should be in little endian
mov RA[eax], ??? ;this is where I don't understand, as which am I to use, dl or dh, but don't we need to use both bytes (dx: 01A3/A301 whatever it is), which would be the value (419) ???
add ebx, 02h ; to skip past the the word address indexes to the next opcode value (44:XOR)
;to cheat/ensure that I jump back to Start, lol:
xor eax,eax
cmp eax, 00h
je start
Store:
(etc etc etc operations/labels, once I get few parts of the load algorithm understood, I should be able to get all of the other operations correct)
ah, so because its '419' it doesn't use the high byte
;------------------------------------------------------------------------------
; HEADING
;------------------------------------------------------------------------------
;redacted
;------------------------------------------------------------------------------
; HISTORY
;------------------------------------------------------------------------------
; Version 1.0
;------------------------------------------------------------------------------
; PURPOSE
;------------------------------------------------------------------------------
; This program's purpose is to emulate a CPU
;------------------------------------------------------------------------------
; MASM BUILD TYPE
;------------------------------------------------------------------------------
.586
;------------------------------------------------------------------------------
; MODEL, STANDARD, and Option TYPES
;------------------------------------------------------------------------------
.MODEL flat, stdcall
option casemap :none
;------------------------------------------------------------------------------
; LIBRARIES/MODULES
;------------------------------------------------------------------------------
;********************************************************
; Masm Include File for Windows 32-Bit API Functions
;
; The information contained in this file can be found at
; http://msdn.microsoft.com/en-us/library/default.aspx
;
;********************************************************
;********************************************************
; WINDOWS API FUNCTION PROTOTYPES
;********************************************************
ExitProcess PROTO : DWORD
GetStdHandle PROTO : DWORD
ReadConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
SetConsoleCursorPosition PROTO : DWORD, : DWORD
SetConsoleMode PROTO : DWORD, : DWORD
SetConsoleTextAttribute PROTO : DWORD, : DWORD
WriteConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
FlushConsoleInputBuffer PROTO : DWORD
CreateThread PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
CreateMutexA PROTO : DWORD, : DWORD, : DWORD
ReleaseMutex PROTO :DWORD
Sleep PROTO : DWORD
WaitForSingleObject PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD, :DWORD, :DWORD
SuspendThread PROTO : DWORD
ResumeThread PROTO : DWORD
ExitThread PROTO : DWORD
CreateFileA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
ReadFile PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
GetFileSize PROTO : DWORD, : DWORD
CloseHandle PROTO : DWORD
TIMECAPS Struct
wPeriodMin DWORD ?
wPeriodMax DWORD ?
TIMECAPS Ends
timeGetDevCaps PROTO : DWORD, : DWORD
timeBeginPeriod PROTO : DWORD
timeGetTime PROTO
GetTickCount PROTO
QueryPerformanceCounter PROTO : DWORD
QueryPerformanceFrequency PROTO : DWORD
GetLastError PROTO
;********************************************************
; EQUATES
;********************************************************
NULL EQU 0
;*****************************************************
; Standard Handles
;*****************************************************
STD_INPUT_HANDLE EQU -10 ;Standard Input Handle
STD_OUTPUT_HANDLE EQU -11 ;Standard Output Handle
STD_ERROR_HANDLE EQU -12 ;Standard Error Handle
GENERIC_ALL EQU 10000000h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
FILE_SHARE_NONE EQU 0
FILE_SHARE_DELETE EQU 4
FILE_SHARE_READ EQU 1
FILE_SHARE_WRITE EQU 2
CREATE_NEW EQU 1
CREATE_ALWAYS EQU 2
OPEN_EXISTING EQU 3
OPEN_ALWAYS EQU 4
TRUNCATE_EXISTING EQU 5
FILE_ATTRIBUTE_NORMAL EQU 80h
;*****************************************************
; Set Console Mode Equates
;
; Refer to Microsoft's documentation on SetConsoleMode
; for a complete description of these equates.
;*****************************************************
ENABLE_NOTHING_INPUT EQU 0000h ;Turn off all input options
ENABLE_ECHO_INPUT EQU 0004h ;Characters read are written to the active screen buffer (can be used with ENABLE_LINE_INPUT)
ENABLE_INSERT_MODE EQU 0020h ;When enabled, text entered in a console window will be inserted at the current cursor location
ENABLE_LINE_INPUT EQU 0002h ;The ReadConsole function returns only when a carriage return character is read.
ENABLE_MOUSE_INPUT EQU 0010h ;If the mouse is within the borders of the console window & the window has the keyboard focus, mouse events are placed in the input buffer. These events are discarded by ReadFile or ReadConsole.
ENABLE_PROCESSED_INPUT EQU 0001h ;CTRL+C is processed by the system and is not placed in the input buffer.
ENABLE_QUICK_EDIT_MODE EQU 0040h ;This flag enables the user to use the mouse to select and edit text. To enable this option, use the OR to combine this flag with ENABLE_EXTENDED_FLAGS.
ENABLE_WINDOW_INPUT EQU 0008h ;User interactions that change the size of the console screen buffer are reported in the console's input buffer.
;If the hConsoleHandle parameter is a screen buffer handle, the mode can be one or more of the following values. When a screen buffer is created, both output modes are enabled by default.
ENABLE_PROCESSED_OUTPUT EQU 0001h ;Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or ReadConsole function are examined for ASCII control sequences and the correct action is performed.
ENABLE_WRAP_AT_EOL_OUTPUT EQU 0002h ;When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the cursor moves to the beginning of the next row when it reaches the end of the current row.
;********************************************************
; CONSOLE FOREGROUND AND BACKGROUND COLOR EQUATES
;********************************************************
FOREGROUND_BLACK EQU 0
FOREGROUND_DARK_BLUE EQU 1
FOREGROUND_DARK_GREEN EQU 2
FOREGROUND_DARK_CYAN EQU 3
FOREGROUND_DARK_RED EQU 4
FOREGROUND_DARK_MAGENTA EQU 5
FOREGROUND_DARK_YELLOW EQU 6
FOREGROUND_GRAY EQU 7
FOREGROUND_DARK_GRAY EQU 8
FOREGROUND_BLUE EQU 9
FOREGROUND_GREEN EQU 10
FOREGROUND_CYAN EQU 11
FOREGROUND_RED EQU 12
FOREGROUND_MAGENTA EQU 13
FOREGROUND_YELLOW EQU 14
FOREGROUND_WHITE EQU 15
BACKGROUND_BLACK EQU FOREGROUND_BLACK * 10h
BACKGROUND_DARK_BLUE EQU FOREGROUND_DARK_BLUE * 10h
BACKGROUND_DARK_GREEN EQU FOREGROUND_DARK_GREEN * 10h
BACKGROUND_DARK_CYAN EQU FOREGROUND_DARK_CYAN * 10h
BACKGROUND_DARK_RED EQU FOREGROUND_DARK_RED * 10h
BACKGROUND_DARK_MAGENTA EQU FOREGROUND_DARK_MAGENTA * 10h
BACKGROUND_DARK_YELLOW EQU FOREGROUND_DARK_YELLOW * 10h
BACKGROUND_GRAY EQU FOREGROUND_GRAY * 10h
BACKGROUND_DARK_GRAY EQU FOREGROUND_DARK_GRAY * 10h
BACKGROUND_BLUE EQU FOREGROUND_BLUE * 10h
BACKGROUND_GREEN EQU FOREGROUND_GREEN * 10h
BACKGROUND_CYAN EQU FOREGROUND_CYAN * 10h
BACKGROUND_RED EQU FOREGROUND_RED * 10h
BACKGROUND_MAGENTA EQU FOREGROUND_MAGENTA * 10h
BACKGROUND_YELLOW EQU FOREGROUND_YELLOW * 10h
BACKGROUND_WHITE EQU FOREGROUND_WHITE * 10h
;------------------------------------------------------------------------------
; STACK SIZE
;------------------------------------------------------------------------------
.STACK 4096
;------------------------------------------------------------------------------
; RADIX TYPE
;------------------------------------------------------------------------------
; (placeholder)
;------------------------------------------------------------------------------
; DATA SEGMENT (DS)
;------------------------------------------------------------------------------
.DATA
;*********************
; EQUATES/ENUMERATORS
;*********************
MAX_RAM EQU 1024
INVALID_HANDLE_VALUE EQU -1
ERROR_ENUM EQU 1
READ_FILE_ERROR EQU 0
NULL_PTR EQU 0
CARRIAGE_RETURN EQU 0Dh
NEW_LINE_FEED EQU 0Ah
ADD_ENUM EQU 11h
SUB_ENUM EQU 22h
XOR_ENUM EQU 44h
LOAD EQU 05h
LOAD_R EQU 55h
STORE EQU 06h
STORE_R EQU 66h
OUT_ENUM EQU 0CCh
JNZ_ENUM EQU 0AAh
HALT EQU 0FFh
;***********
; VARIABLES
;***********
heading byte "redacted", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
history byte "Version 1.0", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
purpose byte "This program's purpose is to emulate a CPU", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
error_file_open byte "ERROR: Unable to open input file", \
CARRIAGE_RETURN, NEW_LINE_FEED
file_name byte "c:\redacted\machine.bin", 0
program_buffer byte MAX_RAM dup (0)
return_code dword 0
bytes_written dword 0
bytes_read dword 0
file_handle dword 0
file_size dword 0
handle_std_out dword 0
handle_std_in dword 0
RA byte 6 dup (0) ; RA = register array (R0-R5)
output_value dword ?
;------------------------------------------------------------------------------
; CODE SEGMENT (CS)
;------------------------------------------------------------------------------
.CODE
Main Proc
;*******************************
; Get handle to standard output
;*******************************
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov handle_std_out, eax
;******************************
; Get handle to standard input
;******************************
invoke GetStdHandle, STD_INPUT_HANDLE
mov handle_std_in, eax
;********************************
; Open existing file for reading
;********************************
invoke CreateFileA, offset file_name, GENERIC_READ, FILE_SHARE_NONE, \
NULL_PTR, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL_PTR
cmp eax, INVALID_HANDLE_VALUE
je Open_Error
mov file_handle, eax
;*******************************************
; Determine the size of the file (in bytes)
;*******************************************
invoke GetFileSize, file_handle, NULL_PTR
mov file_size, eax
;****************************************
; Read the entire file into emulator RAM
;****************************************
invoke ReadFile, file_handle, offset program_buffer, file_size, \
offset bytes_read, NULL_PTR
cmp eax, READ_FILE_ERROR
je Finish
;****************
; Close the file
;****************
invoke CloseHandle, file_handle
Pre_Start:
invoke WriteConsoleA, handle_std_out, OFFSET heading, SIZEOF heading, \
OFFSET bytes_written, NULL_PTR
invoke WriteConsoleA, handle_std_out, OFFSET history, SIZEOF history, \
OFFSET bytes_written, NULL_PTR
invoke WriteConsoleA, handle_std_out, OFFSET purpose, SIZEOF purpose, \
OFFSET bytes_written, NULL_PTR
xor ebx, ebx
mov ecx, LENGTHOF program_buffer
Start:
sub ecx, 01h
cmp program_buffer[ebx], LOAD
je Load
cmp program_buffer[ebx], STORE
je Store
cmp program_buffer[ebx], ADD_ENUM
je Add_Enum
cmp program_buffer[ebx], SUB_ENUM
je Sub_Enum
cmp program_buffer[ebx], XOR_ENUM
je Xor_Enum
cmp program_buffer[ebx], LOAD_R
je Load_R
cmp program_buffer[ebx], STORE_R
je Store_R
cmp program_buffer[ebx], JNZ_ENUM
je Jnz_Enum
cmp program_buffer[ebx], OUT_ENUM
je Out_Enum
cmp program_buffer[ebx], HALT
je Finish
cmp ecx, 00h ; or its 01h
je Finish
add ebx, 01h
jne Start
Load:
add ebx, 01h
movzx eax, program_buffer[ebx]
add ebx, 01h
movzx edx, word ptr program_buffer[ebx]
xchg dh, dl
mov RA[eax], dl
add ebx, 02h
xor eax, eax
cmp eax, 00h
je Start
Store:
add ebx, 01h
movzx ax, RA[0]
xchg ah, al
mov word ptr program_buffer[ebx], ax
add ebx, 02h
xor eax, eax
cmp eax, 00h
je Start
Add_Enum:
add ebx, 01h
movzx edi, program_buffer[ebx]
movzx eax, RA[edi]
add ebx, 01h
movzx esi, program_buffer[ebx]
movzx edx, RA[esi]
add eax, edx
mov RA[edi], al
add ebx, 01h
xor eax, eax
cmp eax, 00h
je Start
Sub_Enum:
add ebx, 01h
movzx edi, program_buffer[ebx]
movzx eax, RA[edi]
add ebx, 01h
movzx esi, program_buffer[ebx]
movzx edx, RA[esi]
sub eax, edx
mov RA[edi], al
add ebx, 01h
xor eax, eax
cmp eax, 00h
je Start
Xor_Enum:
add ebx, 01h
movzx eax, program_buffer[ebx]
mov edi, eax
add ebx, 01h
movzx edx, program_buffer[ebx]
xor eax, edx
mov RA[edi], al
add ebx, 01h
xor eax, eax
cmp eax, 00h
je Start
Load_R:
add ebx, 01h
movzx eax, program_buffer[ebx]
movzx edi, RA[eax]
add ebx, 01h
movzx edx, program_buffer[ebx+edi]
xchg dh, dl
mov RA[eax], dl
add ebx, 02h
xor eax, eax
cmp eax, 00h
je Start
Store_R:
add ebx, 01h
movzx edx, RA[0]
xchg dh, dl
movzx eax, program_buffer[ebx]
movzx edi, RA[eax]
add ebx, 01h
mov word ptr program_buffer[ebx+edi], dx
add ebx, 02h
xor eax, eax
cmp eax, 00h
je Start
Jnz_Enum:
add ebx, 01h
movzx eax, program_buffer[ebx]
cmp eax, 00h
add ebx, 01h
jne Start
add ebx, 02h
xor eax, eax
cmp eax, 00h
je Start
Out_Enum:
add ebx, 01h
movzx eax, program_buffer[ebx]
movzx edx, RA[eax]
mov output_value, edx
invoke WriteConsoleA, handle_std_out, OFFSET output_value, \
SIZEOF output_value, OFFSET bytes_written, NULL_PTR
add ebx, 01h
xor eax, eax
cmp eax, 00h
je Start
Open_Error:
invoke WriteConsoleA, handle_std_out, offset error_file_open, \
sizeof error_file_open, offset bytes_written, NULL_PTR
mov return_code, ERROR_ENUM
Finish:
invoke ExitProcess, return_code
Main endp
END Main
£D £ ¡DU DD¡DDU DDU DDf Df U DDU¤DÌ£¢"ªÿc7¦„ÌqåZÍ
!"#$%&'()*+,-./012345689:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY [\]^_`abdefghijklmnoprstuvwxyz{|}~€‚ƒ…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊË
ÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäæçèéêëìíîïðñòóôõö÷øùúûüýþÿ®‹ü/©àÖèB$GX31ã÷Í©ÝeÐMj~Íß¹ÞöNýω%éGý¶5Šc"‡[RE#‹Ã©0
´ÐþÁòðqhíæÝ-
W"‡™L€×'-s'€/À)ž=1t„dˆ3r »üÖ.&¤\øTmÅâN£Aî8ù‚nÜÅzyÅÙt?¤>f6L¿´½š‚6@P•ô’½w¹¢¾Žz˜,Žn«Ê
add ebx, 01h ; increment past the opcode
movzx eax, program_buffer[ebx] ; read the next byte to get the register
add ebx, 01h ; increment past the register byte
movzx edx, word ptr program_buffer[ebx] ; load the *address* of the byte to read from memory.
xchg dh, dl ; swap the bytes of the address, so you can use them as a 16-bit number.
mov dl, program_buffer[edx] ; <- add this line, which goes out to memory at the address in edx and gets the byte there
mov RA[eax], dl ; store the read byte in the register.
xor eax, eax
cmp eax, 00h
je Start
jmp Start
; increment past the opcode - rather than do this in every instruction, you could just do it before you start branching.
add ebx, 01h
; grab the value in R0
movzx ax, RA[0]
; you don't needs to do this. The value you care about is in AL (an 8-bit value). Swapping just confuses things.
xchg ah, al
; here you actually overwrite your own code in the program buffer with 16 bits of data
mov word ptr program_buffer[ebx], ax
; then you skip past the damage. You've actually stored a 16-bit version of R0 over the address you were meant to use.
add ebx, 02h
; increment past the opcode - rather than do this in every instruction, you could just do it before you start branching.
add ebx, 01h
; grab the value in R0 . Not sure why you don't just use mov al, RA[0], but maybe there's a reason.
movzx ax, RA[0]
;; Grab the address where you need to store the byte value
movzx edx, word ptr program_buffer[ebx]
;; swap it so you can use it
xchg dh, dl
add ebx, 02h
;; store the byte into the desired address
mov program_buffer[edx], al
movzx edx, program_buffer[ebx+edi]
mov word ptr program_buffer[ebx+edi], dx
add ebx, 01h ; increment to register
movzx eax, program_buffer[ebx] ; load the byte register index
add ebx, 01h ; increment past register to address
movzx edx, word ptr program_buffer[ebx] ; load the address that will be jumped to if register is not 0
xchg dh, dl ; get it in usable form
add ebx, 2 ; skip past the addresss
;; now you're set to do something. You have the register and the address to jump to.
cmp byte ptr RA[eax], 0 ; is the register 0?
je Start ; go to next instruction
;; And here's the magic
mov ebx, edx ; set the instruction pointer to the address that was in the instruction
jmp Start ; go to next instruction
;------------------------------------------------------------------------------
; HEADING
;------------------------------------------------------------------------------
;redacted
;------------------------------------------------------------------------------
; HISTORY
;------------------------------------------------------------------------------
; Version 1.0
;------------------------------------------------------------------------------
; PURPOSE
;------------------------------------------------------------------------------
; This program's purpose is to emulate a CPU
;------------------------------------------------------------------------------
; MASM BUILD TYPE
;------------------------------------------------------------------------------
.586
;------------------------------------------------------------------------------
; MODEL, STANDARD, and Option TYPES
;------------------------------------------------------------------------------
.MODEL flat, stdcall
option casemap :none
;------------------------------------------------------------------------------
; LIBRARIES/MODULES
;------------------------------------------------------------------------------
;********************************************************
; Masm Include File for Windows 32-Bit API Functions
;
; The information contained in this file can be found at
; http://msdn.microsoft.com/en-us/library/default.aspx
;
;********************************************************
;********************************************************
; WINDOWS API FUNCTION PROTOTYPES
;********************************************************
ExitProcess PROTO : DWORD
GetStdHandle PROTO : DWORD
ReadConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
SetConsoleCursorPosition PROTO : DWORD, : DWORD
SetConsoleMode PROTO : DWORD, : DWORD
SetConsoleTextAttribute PROTO : DWORD, : DWORD
WriteConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
FlushConsoleInputBuffer PROTO : DWORD
CreateThread PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
CreateMutexA PROTO : DWORD, : DWORD, : DWORD
ReleaseMutex PROTO :DWORD
Sleep PROTO : DWORD
WaitForSingleObject PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD, :DWORD, :DWORD
SuspendThread PROTO : DWORD
ResumeThread PROTO : DWORD
ExitThread PROTO : DWORD
CreateFileA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
ReadFile PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
GetFileSize PROTO : DWORD, : DWORD
CloseHandle PROTO : DWORD
TIMECAPS Struct
wPeriodMin DWORD ?
wPeriodMax DWORD ?
TIMECAPS Ends
timeGetDevCaps PROTO : DWORD, : DWORD
timeBeginPeriod PROTO : DWORD
timeGetTime PROTO
GetTickCount PROTO
QueryPerformanceCounter PROTO : DWORD
QueryPerformanceFrequency PROTO : DWORD
GetLastError PROTO
;********************************************************
; EQUATES
;********************************************************
NULL EQU 0
;*****************************************************
; Standard Handles
;*****************************************************
STD_INPUT_HANDLE EQU -10 ;Standard Input Handle
STD_OUTPUT_HANDLE EQU -11 ;Standard Output Handle
STD_ERROR_HANDLE EQU -12 ;Standard Error Handle
GENERIC_ALL EQU 10000000h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
FILE_SHARE_NONE EQU 0
FILE_SHARE_DELETE EQU 4
FILE_SHARE_READ EQU 1
FILE_SHARE_WRITE EQU 2
CREATE_NEW EQU 1
CREATE_ALWAYS EQU 2
OPEN_EXISTING EQU 3
OPEN_ALWAYS EQU 4
TRUNCATE_EXISTING EQU 5
FILE_ATTRIBUTE_NORMAL EQU 80h
;*****************************************************
; Set Console Mode Equates
;
; Refer to Microsoft's documentation on SetConsoleMode
; for a complete description of these equates.
;*****************************************************
ENABLE_NOTHING_INPUT EQU 0000h ;Turn off all input options
ENABLE_ECHO_INPUT EQU 0004h ;Characters read are written to the active screen buffer (can be used with ENABLE_LINE_INPUT)
ENABLE_INSERT_MODE EQU 0020h ;When enabled, text entered in a console window will be inserted at the current cursor location
ENABLE_LINE_INPUT EQU 0002h ;The ReadConsole function returns only when a carriage return character is read.
ENABLE_MOUSE_INPUT EQU 0010h ;If the mouse is within the borders of the console window & the window has the keyboard focus, mouse events are placed in the input buffer. These events are discarded by ReadFile or ReadConsole.
ENABLE_PROCESSED_INPUT EQU 0001h ;CTRL+C is processed by the system and is not placed in the input buffer.
ENABLE_QUICK_EDIT_MODE EQU 0040h ;This flag enables the user to use the mouse to select and edit text. To enable this option, use the OR to combine this flag with ENABLE_EXTENDED_FLAGS.
ENABLE_WINDOW_INPUT EQU 0008h ;User interactions that change the size of the console screen buffer are reported in the console's input buffer.
;If the hConsoleHandle parameter is a screen buffer handle, the mode can be one or more of the following values. When a screen buffer is created, both output modes are enabled by default.
ENABLE_PROCESSED_OUTPUT EQU 0001h ;Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or ReadConsole function are examined for ASCII control sequences and the correct action is performed.
ENABLE_WRAP_AT_EOL_OUTPUT EQU 0002h ;When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the cursor moves to the beginning of the next row when it reaches the end of the current row.
;********************************************************
; CONSOLE FOREGROUND AND BACKGROUND COLOR EQUATES
;********************************************************
FOREGROUND_BLACK EQU 0
FOREGROUND_DARK_BLUE EQU 1
FOREGROUND_DARK_GREEN EQU 2
FOREGROUND_DARK_CYAN EQU 3
FOREGROUND_DARK_RED EQU 4
FOREGROUND_DARK_MAGENTA EQU 5
FOREGROUND_DARK_YELLOW EQU 6
FOREGROUND_GRAY EQU 7
FOREGROUND_DARK_GRAY EQU 8
FOREGROUND_BLUE EQU 9
FOREGROUND_GREEN EQU 10
FOREGROUND_CYAN EQU 11
FOREGROUND_RED EQU 12
FOREGROUND_MAGENTA EQU 13
FOREGROUND_YELLOW EQU 14
FOREGROUND_WHITE EQU 15
BACKGROUND_BLACK EQU FOREGROUND_BLACK * 10h
BACKGROUND_DARK_BLUE EQU FOREGROUND_DARK_BLUE * 10h
BACKGROUND_DARK_GREEN EQU FOREGROUND_DARK_GREEN * 10h
BACKGROUND_DARK_CYAN EQU FOREGROUND_DARK_CYAN * 10h
BACKGROUND_DARK_RED EQU FOREGROUND_DARK_RED * 10h
BACKGROUND_DARK_MAGENTA EQU FOREGROUND_DARK_MAGENTA * 10h
BACKGROUND_DARK_YELLOW EQU FOREGROUND_DARK_YELLOW * 10h
BACKGROUND_GRAY EQU FOREGROUND_GRAY * 10h
BACKGROUND_DARK_GRAY EQU FOREGROUND_DARK_GRAY * 10h
BACKGROUND_BLUE EQU FOREGROUND_BLUE * 10h
BACKGROUND_GREEN EQU FOREGROUND_GREEN * 10h
BACKGROUND_CYAN EQU FOREGROUND_CYAN * 10h
BACKGROUND_RED EQU FOREGROUND_RED * 10h
BACKGROUND_MAGENTA EQU FOREGROUND_MAGENTA * 10h
BACKGROUND_YELLOW EQU FOREGROUND_YELLOW * 10h
BACKGROUND_WHITE EQU FOREGROUND_WHITE * 10h
;------------------------------------------------------------------------------
; STACK SIZE
;------------------------------------------------------------------------------
.STACK 4096
;------------------------------------------------------------------------------
; RADIX TYPE
;------------------------------------------------------------------------------
; (placeholder)
;------------------------------------------------------------------------------
; DATA SEGMENT (DS)
;------------------------------------------------------------------------------
.DATA
;*********************
; EQUATES/ENUMERATORS
;*********************
MAX_RAM EQU 1024
INVALID_HANDLE_VALUE EQU -1
ERROR_ENUM EQU 1
READ_FILE_ERROR EQU 0
NULL_PTR EQU 0
CARRIAGE_RETURN EQU 0Dh
NEW_LINE_FEED EQU 0Ah
ADD_ENUM EQU 11h
SUB_ENUM EQU 22h
XOR_ENUM EQU 44h
LOAD EQU 05h
LOAD_R EQU 55h
STORE EQU 06h
STORE_R EQU 66h
OUT_ENUM EQU 0CCh
JNZ_ENUM EQU 0AAh
HALT EQU 0FFh
;***********
; VARIABLES
;***********
heading byte "redacted", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
history byte "Version 1.0", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
purpose byte "This program's purpose is to emulate a CPU", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
error_file_open byte "ERROR: Unable to open input file", \
CARRIAGE_RETURN, NEW_LINE_FEED
file_name byte "c:\redacted\machine.bin", 0
program_buffer byte MAX_RAM dup (0)
return_code dword 0
bytes_written dword 0
bytes_read dword 0
file_handle dword 0
file_size dword 0
handle_std_out dword 0
handle_std_in dword 0
RA byte 6 dup (0) ; RA = register array (R0-R5)
output_value dword ?
coding_error byte "You have an error in your code at index: "
coding_error_index dword ?
;------------------------------------------------------------------------------
; CODE SEGMENT (CS)
;------------------------------------------------------------------------------
.CODE
Main Proc
;*******************************
; Get handle to standard output
;*******************************
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov handle_std_out, eax
;******************************
; Get handle to standard input
;******************************
invoke GetStdHandle, STD_INPUT_HANDLE
mov handle_std_in, eax
;********************************
; Open existing file for reading
;********************************
invoke CreateFileA, offset file_name, GENERIC_READ, FILE_SHARE_NONE, \
NULL_PTR, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL_PTR
cmp eax, INVALID_HANDLE_VALUE
je Open_Error
mov file_handle, eax
;*******************************************
; Determine the size of the file (in bytes)
;*******************************************
invoke GetFileSize, file_handle, NULL_PTR
mov file_size, eax
;****************************************
; Read the entire file into emulator RAM
;****************************************
invoke ReadFile, file_handle, offset program_buffer, file_size, \
offset bytes_read, NULL_PTR
cmp eax, READ_FILE_ERROR
je Finish
;****************
; Close the file
;****************
invoke CloseHandle, file_handle
Pre_Start:
invoke WriteConsoleA, handle_std_out, OFFSET heading, SIZEOF heading, \
OFFSET bytes_written, NULL_PTR
invoke WriteConsoleA, handle_std_out, OFFSET history, SIZEOF history, \
OFFSET bytes_written, NULL_PTR
invoke WriteConsoleA, handle_std_out, OFFSET purpose, SIZEOF purpose, \
OFFSET bytes_written, NULL_PTR
xor ebx, ebx
Start:
cmp program_buffer[ebx], LOAD
je Load
cmp program_buffer[ebx], STORE
je Store
cmp program_buffer[ebx], ADD_ENUM
je Add_Enum
cmp program_buffer[ebx], SUB_ENUM
je Sub_Enum
cmp program_buffer[ebx], XOR_ENUM
je Xor_Enum
cmp program_buffer[ebx], LOAD_R
je Load_R
cmp program_buffer[ebx], STORE_R
je Store_R
cmp program_buffer[ebx], JNZ_ENUM
je Jnz_Enum
cmp program_buffer[ebx], OUT_ENUM
je Out_Enum
cmp program_buffer[ebx], HALT
je Finish
jmp near ptr Catch_Coding_Error
Load:
add ebx, 01h
movzx edi, program_buffer[ebx]
add ebx, 01h
movzx edx, word ptr program_buffer[ebx]
xchg dh, dl
mov al, program_buffer[edx]
mov RA[edi], al
add ebx, 02h
jmp near ptr Start
Store:
add ebx, 01h
movzx edx, word ptr program_buffer[ebx]
xchg dh, dl
movzx ax, RA[0]
mov program_buffer[edx], al
add ebx, 02h
jmp near ptr Start
Add_Enum:
add ebx, 01h
movzx edi, program_buffer[ebx]
movzx eax, RA[edi]
add ebx, 01h
movzx esi, program_buffer[ebx]
movzx edx, RA[esi]
add eax, edx
mov RA[edi], al
add ebx, 01h
jmp near ptr Start
Sub_Enum:
add ebx, 01h
movzx edi, program_buffer[ebx]
movzx eax, RA[edi]
add ebx, 01h
movzx esi, program_buffer[ebx]
movzx edx, RA[esi]
sub eax, edx
mov RA[edi], al
add ebx, 01h
jmp near ptr Start
Xor_Enum:
add ebx, 01h
movzx eax, program_buffer[ebx]
mov edi, eax
add ebx, 01h
movzx edx, program_buffer[ebx]
xor eax, edx
mov RA[edi], al
add ebx, 01h
jmp near ptr Start
Load_R:
add ebx, 01h
movzx esi, program_buffer[ebx]
movzx edi, RA[esi]
add ebx, 01h
movzx edx, word ptr program_buffer[ebx]
xchg dh, dl
movzx eax, program_buffer[edx+edi]
mov RA[esi], al
add ebx, 02h
jmp near ptr Start
Store_R:
add ebx, 01h
movzx esi, program_buffer[ebx]
movzx edi, RA[esi]
movzx eax, RA[0]
add ebx, 01h
movzx edx, word ptr program_buffer[ebx]
xchg dh, dl
mov word ptr program_buffer[edx+edi], ax
add ebx, 02h
jmp near ptr Start
Jnz_Enum:
add ebx, 01h
movzx eax, program_buffer[ebx]
movzx esi, RA[eax]
add ebx, 01h
movzx edx, program_buffer[ebx]
xchg dh, dl
add ebx, 02h
cmp esi, dword ptr 00h
je Start
mov ebx, edx
jmp near ptr Start
Out_Enum:
add ebx, 01h
movzx eax, program_buffer[ebx]
movzx edx, RA[eax]
mov output_value, edx
invoke WriteConsoleA, handle_std_out, OFFSET output_value, \
SIZEOF output_value, OFFSET bytes_written, NULL_PTR
add ebx, 01h
jmp near ptr Start
Catch_Coding_Error:
invoke WriteConsoleA, handle_std_out, OFFSET coding_error, \
SIZEOF coding_error, OFFSET bytes_written, NULL_PTR
mov coding_error_index, ebx
invoke WriteConsoleA, handle_std_out, OFFSET coding_error_index, \
SIZEOF coding_error_index, OFFSET bytes_written, NULL_PTR
jmp near ptr Finish
Open_Error:
invoke WriteConsoleA, handle_std_out, offset error_file_open, \
sizeof error_file_open, offset bytes_written, NULL_PTR
mov return_code, ERROR_ENUM
Finish:
invoke ExitProcess, return_code
Main endp
END Main
the debugger's stepping does a pretty good job of what operation it's doing... the problem is with such as when it gets an address or value, is that the right address value, is it doing the correct operation's details/specifics or not...
0000 0000 05 04 01 A3 44 02 02 05 00 01 A0 05 04 01 A3 11 .... D... .... ....
0000 0010 00 04 06 01 A0 05 03 01 A1 44 01 01 11 01 00 55 .... .... .D.. ...U
0000 0020 01 00 A0 11 03 01 44 05 05 11 05 00 44 00 00 11 .... ..D. .... D...
0000 0030 00 03 06 01 1A 44 00 00 11 00 05 44 01 01 11 01 .... .D.. ...D ....
0000 0040 03 55 01 00 A0 44 05 05 11 05 01 44 01 01 11 01 .U.. .D.. ...D ....
0000 0050 00 55 01 00 A0 44 04 04 11 04 00 44 00 00 11 00 .U.. .D.. ...D ....
0000 0060 01 66 03 00 A0 44 00 00 11 00 05 66 04 00 A0 11 .f.. .D.. ...f ....
0000 0070 01 05 55 01 00 A0 44 04 04 11 04 01 44 01 01 11 ..U. ..D. .... D...
0000 0080 01 02 55 01 01 A4 44 01 04 CC 01 05 04 01 A3 05 ..U. ..D. .... ....
0000 0090 05 01 A2 11 02 04 22 05 02 AA 05 00 07 FF 00 00 .... ..". .... ....
0000 00A0 63 06 37 A6 16 84 CC 71 E5 5A CD 0B 0C 0D 0E 0F c.7. ...q .Z.. ....
0000 00B0 10 11 12 13 14 15 04 17 18 19 1A 1B 1C 1D 1E 1F .... .... .... ....
0000 00C0 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F !"# $%&' ()*+ ,-./
0000 00D0 30 31 32 33 34 35 36 02 38 39 3A 3B 3C 3D 3E 3F 0123 456. 89:; <=>?
0000 00E0 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F @ABC DEFG HIJK LMNO
0000 00F0 50 51 52 53 54 55 56 57 58 59 09 5B 5C 5D 5E 5F PQRS TUVW XY.[ \]^_
0000 0100 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F `ab. defg hijk lmno
0000 0110 70 07 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F p.rs tuvw xyz{ |}~.
0000 0120 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F .... .... .... ....
0000 0130 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F .... .... .... ....
0000 0140 A0 A1 A2 A3 A4 A5 03 A7 A8 A9 AA AB AC AD AE AF .... .... .... ....
0000 0150 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF .... .... .... ....
0000 0160 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB 01 0A CE CF .... .... .... ....
0000 0170 D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF .... .... .... ....
0000 0180 E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF .... .... .... ....
0000 0190 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF .... .... .... ....
0000 01A0 00 00 AE 01 8B 1B FC 2F A9 E0 11 D6 E8 42 24 47 .... .../ .... .B$G
0000 01B0 58 33 31 12 00 E3 F7 CD A9 DD 65 D0 17 4D 6A 7E X31. .... ..e. .MJ~
0000 01C0 1F CD DF B9 DE F6 03 4E 1C FD CF 89 25 E9 47 FD .... ...N .... %.G.
0000 01D0 B6 35 01 8A 63 22 87 5B 52 0F 45 23 8B C3 A9 30 .5.. c".[ R.E# ...0
0000 01E0 0D B4 D0 FE C1 F2 00 F0 71 68 ED E6 15 04 DD 19 .... .... qh.. ....
0000 01F0 2D 0A 9D 57 22 87 99 4C 80 18 D7 27 2D 73 27 80 -..w "..L ...' -s'.
0000 0200 2F C0 29 9E 8F 3D 31 1D 74 84 64 88 33 1D 72 20 /.). .=1. t.d. 3.r
0000 0210 BB FC D6 2E 26 A4 16 5C F8 54 6D C5 E2 4E A3 41 .... &..\ .Tm. .N.A
0000 0220 EE 12 38 1A F9 82 6E DC C5 7A 79 02 C5 D9 74 3F ..8. ..n. .zy. ..t?
0000 0230 A4 3E 66 36 4C BF B4 BD 9A 82 36 40 90 50 95 F4 .>f6 L... ..6@ .P..
0000 0240 92 BD 77 B9 17 A2 BE 8E 1B 7A 98 2C 1E 8E 16 6E ..W. .... z.., ...N
0000 0250 AB CA ..
0000 0000 05 . LOAD
0000 0001 04 . REG4
0000 0002 01 . 01
0000 0003 A3 . A3
0000 0004 44 D XOR
0000 0005 02 . REG2
0000 0006 02 . REG2
0000 0007 05 . LOAD
0000 0008 00 . REG0
0000 0009 01 . 01
0000 000A A0 . A0
0000 000B 05 . LOAD
0000 000C 04 . REG4
0000 000D 01 . 01
0000 000E A3 . A3
0000 000F 11 . ADD
--------------------
0000 0010 00 . REG0
0000 0011 04 . REG4
0000 0012 06 . STORE
0000 0013 01 . 01
0000 0014 A0 . A0
0000 0015 05 . LOAD
0000 0016 03 . REG3
0000 0017 01 . 01
0000 0018 A1 . A1
0000 0019 44 D XOR
0000 001A 01 . REG1
0000 001B 01 . REG1
0000 001C 11 . ADD
0000 001D 01 . REG1
0000 001E 00 . REG0
0000 001F 55 U LOADR
---------------------
0000 0020 01 . REG1
0000 0021 00 . 00
0000 0022 A0 . A0
0000 0023 11 . ADD
0000 0024 03 . REG3
0000 0025 01 . REG1
0000 0026 44 D XOR
0000 0027 05 . REG5
0000 0028 05 . REG5
0000 0029 11 . ADD
0000 002A 05 . REG5
0000 002B 00 . REG0
0000 002C 44 D XOR
0000 002D 00 . REG0
0000 002E 00 . REG0
0000 002F 11 . ADD
-----------------------
0000 0030 00 . REG0
0000 0031 03 . REG3
0000 0032 06 . STORE
0000 0033 01 . 01
0000 0034 1A . 1A
0000 0035 44 D XOR
0000 0036 00 . REG0
0000 0037 00 . REG0
0000 0038 11 . ADD
0000 0039 00 . REG0
0000 003A 05 . REG5
0000 003B 44 D XOR
0000 003C 01 . REG1
0000 003D 01 . REG1
0000 003E 11 . ADD
0000 003F 01 . REG1
----------------------
0000 0040 03 . REG3
0000 0041 55 U LOADR
0000 0042 01 . REG1
0000 0043 00 . 00
0000 0044 A0 . A0
0000 0045 44 D XOR
0000 0046 05 . REG5
0000 0047 05 . REG5
0000 0048 11 . ADD
0000 0049 05 . REG5
0000 004A 01 . REG1
0000 004B 44 D XOR
0000 004C 01 . REG1
0000 004D 01 . REG1
0000 004E 11 . ADD
0000 004F 01 . REG1
-----------------------
0000 0050 00 . REG0
0000 0051 55 U LOADR
0000 0052 01 . REG1
0000 0053 00 . 00
0000 0054 A0 . A0
0000 0055 44 D XOR
0000 0056 04 . REG4
0000 0057 04 . REG4
0000 0058 11 . ADD
0000 0059 04 . REG4
0000 005A 00 . REG0
0000 005B 44 D XOR
0000 005C 00 . REG0
0000 005D 00 . REG0
0000 005E 11 . ADD
0000 005F 00 . REG0
----------------------
0000 0060 01 . REG1
0000 0061 66 f STORER
0000 0062 03 . REG3
0000 0063 00 . 00
0000 0064 A0 . A0
0000 0065 44 D XOR
0000 0066 00 . REG0
0000 0067 00 . REG0
0000 0068 11 . ADD
0000 0069 00 . REG0
0000 006A 05 . REG5
0000 006B 66 f STORER
0000 006C 04 . REG4
0000 006D 00 . 00
0000 006E A0 . A0
0000 006F 11 . ADD
----------------------
0000 0070 01 . REG1
0000 0071 05 . REG5
0000 0072 55 U LOADR
0000 0073 01 . REG1
0000 0074 00 . 00
0000 0075 A0 . A0
0000 0076 44 D XOR
0000 0077 04 . REG4
0000 0078 04 . REG4
0000 0079 11 . ADD
0000 007A 04 . REG4
0000 007B 01 . REG1
0000 007C 44 D XOR
0000 007D 01 . REG1
0000 007E 01 . REG1
0000 007F 11 . ADD
-----------------------
0000 0080 01 . REG1
0000 0081 02 . REG2
0000 0082 55 U LOADR
0000 0083 01 . RG1
0000 0084 01 . 01
0000 0085 A4 . A4
0000 0086 44 D XOR
0000 0087 01 . REG1
0000 0088 04 . REG4
0000 0089 CC . OUT
0000 008A 01 . REG1
0000 008B 05 . LOAD
0000 008C 04 . REG2
0000 008D 01 . 01
0000 008E A3 . A3
0000 008F 05 . LOAD
---------------------
0000 0090 05 . REG5
0000 0091 01 . 01
0000 0092 A2 . A2
0000 0093 11 . ADD
0000 0094 02 . REG2
0000 0095 04 . REG4
0000 0096 22 " SUB
0000 0097 05 . REG5
0000 0098 02 . REG2
0000 0099 AA . JNZ
0000 009A 05 . REG5
0000 009B 00 . 00
0000 009C 07 . 07
0000 009D FF . HALT
0000 009E 00 .
0000 009F 00 .
------------------------
0000 00A0 63 c
0000 00A1 06 .
0000 00A2 37 7
0000 00A3 A6 .
0000 00A4 16 .
0000 00A5 84 .
0000 00A6 CC .
0000 00A7 71 q
0000 00A8 E5 .
0000 00A9 5A Z
0000 00AA CD .
0000 00AB 0B .
0000 00AC 0C .
0000 00AD 0D .
0000 00AE 0E .
0000 00AF 0F .
------------------------
0000 00B0 10 .
0000 00B1 11 .
0000 00B2 12 .
0000 00B3 13 .
0000 00B4 14 .
0000 00B5 15 .
0000 00B6 04 .
0000 00B7 17 .
0000 00B8 18 .
0000 00B9 19 .
0000 00BA 1A .
0000 00BB 1B .
0000 00BC 1C .
0000 00BD 1D .
0000 00BE 1E .
0000 00BF 1F .
----------------------------
0000 00C0 20
0000 00C1 21 !
0000 00C2 22 "
0000 00C3 23 #
0000 00C4 24 $
0000 00C5 25 %
0000 00C6 26 &
0000 00C7 27 '
0000 00C8 28 (
0000 00C9 29 )
0000 00CA 2A *
0000 00CB 2B +
0000 00CC 2C ,
0000 00CD 2D -
0000 00CE 2E .
0000 00CF 2F /
-----------------
0000 00D0 30 0
0000 00D1 31 1
0000 00D2 32 2
0000 00D3 33 3
0000 00D4 34 4
0000 00D5 35 5
0000 00D6 36 6
0000 00D7 02 .
0000 00D8 38 8
0000 00D9 39 9
0000 00DA 3A :
0000 00DB 3B ;
0000 00DC 3C <
0000 00DD 3D =
0000 00DE 3E >
0000 00DF 3F ?
--------------------
0000 00E0 40 @
0000 00E1 41 A
0000 00E2 42 B
0000 00E3 43 C
0000 00E4 44 D
0000 00E5 45 E
0000 00E6 46 F
0000 00E7 47 G
0000 00E8 48 H
0000 00E9 49 I
0000 00EA 4A J
0000 00EB 4B K
0000 00EC 4C L
0000 00ED 4D M
0000 00EE 4E N
0000 00EF 4F O
---------------------
0000 00F0 50 P
0000 00F1 51 Q
0000 00F2 52 R
0000 00F3 53 S
0000 00F4 54 T
0000 00F5 55 U
0000 00F6 56 V
0000 00F7 57 W
0000 00F8 58 X
0000 00F9 59 Y
0000 00FA 09 .
0000 00FB 5B [
0000 00FC 5C \
0000 00FD 5D ]
0000 00FE 5E ^
0000 00FF 5F _
-----------------------
0000 0100 60 `
0000 0101 61 a
0000 0102 62 b
0000 0103 63 .
0000 0104 64 d
0000 0105 65 e
0000 0106 66 f
0000 0107 67 g
0000 0108 68 h
0000 0109 69 i
0000 010A 6A j
0000 010B 6B k
0000 010C 6C l
0000 010D 6D m
0000 010E 6E n
0000 010F 6F o
----------------------
0000 0110 70 p
0000 0111 07 .
0000 0112 72 r
0000 0113 73 s
0000 0114 74 t
0000 0115 75 u
0000 0116 76 v
0000 0117 77 w
0000 0118 78 x
0000 0119 79 y
0000 011A 7A z
0000 011B 7B {
0000 011C 7C |
0000 011D 7D }
0000 011E 7E ~
0000 011F 7F .
-----------------------
0000 0120 80 .
0000 0121 81 .
0000 0122 82 .
0000 0123 83 .
0000 0124 84 .
0000 0125 85 .
0000 0126 86 .
0000 0127 87 .
0000 0128 88 .
0000 0129 89 .
0000 012A 8A .
0000 012B 8B .
0000 012C 8C .
0000 012D 8D .
0000 012E 8E .
0000 012F 8F .
------------------
0000 0130 90 .
0000 0131 91 .
0000 0132 92 .
0000 0133 93 .
0000 0134 94 .
0000 0135 95 .
0000 0136 96 .
0000 0137 97 .
0000 0138 98 .
0000 0139 99 .
0000 013A 9A .
0000 013B 9B .
0000 013C 9C .
0000 013D 9D .
0000 013E 9E .
0000 013F 9F .
----------------------
0000 0140 A0 .
0000 0141 A1 .
0000 0142 A2 .
0000 0143 A3 .
0000 0144 A4 .
0000 0145 A5 .
0000 0146 03 .
0000 0147 A7 .
0000 0148 A8 .
0000 0149 A9 .
0000 014A AA .
0000 014B AB .
0000 014C AC .
0000 014D AD .
0000 014E AE .
0000 014F AF .
-----------------------
0000 0150 B0 .
0000 0151 B1 .
0000 0152 B2 .
0000 0153 B3 .
0000 0154 B4 .
0000 0155 B5 .
0000 0156 B6 .
0000 0157 B7 .
0000 0158 B8 .
0000 0159 B9 .
0000 015A BA .
0000 015B BB .
0000 015C BC .
0000 015D BD .
0000 015E BE .
0000 015F BF .
------------------
0000 0160 C0 .
0000 0161 C1 .
0000 0162 C2 .
0000 0163 C3 .
0000 0164 C4 .
0000 0165 C5 .
0000 0166 C6 .
0000 0167 C7 .
0000 0168 C8 .
0000 0169 C9 .
0000 016A CA .
0000 016B CB .
0000 016C 01 .
0000 016D 0A .
0000 016E CE .
0000 016F CF .
----------------------
0000 0170 D0 .
0000 0171 D1 .
0000 0172 D2 .
0000 0173 D3 .
0000 0174 D4 .
0000 0175 D5 .
0000 0176 D6 .
0000 0177 D7 .
0000 0178 D8 .
0000 0179 D9 .
0000 017A DA .
0000 017B DB .
0000 017C DC .
0000 017D DD .
0000 017E DE .
0000 017F DF .
-----------------------
0000 0180 E0 .
0000 0181 E1 .
0000 0182 E2 .
0000 0183 E3 .
0000 0184 E4 .
0000 0185 E5 .
0000 0186 E6 .
0000 0187 E7 .
0000 0188 E8 .
0000 0189 E9 .
0000 018A EA .
0000 018B EB .
0000 018C EC .
0000 018D ED .
0000 018E EE .
0000 018F EF .
------------------
0000 0190 F0 .
0000 0191 F1 .
0000 0192 F2 .
0000 0193 F3 .
0000 0194 F4 .
0000 0195 F5 .
0000 0196 F6 .
0000 0197 F7 .
0000 0198 F8 .
0000 0199 F9 .
0000 019A FA .
0000 019B FB .
0000 019C FC .
0000 019D FD .
0000 019E FE .
0000 019F FF .
----------------------
0000 01A0 00 .
0000 01A1 00 .
0000 01A2 AE .
0000 01A3 01 .
0000 01A4 8B .
0000 01A5 1B .
0000 01A6 FC .
0000 01A7 2F /
0000 01A8 A9 .
0000 01A9 E0 .
0000 01AA 11 .
0000 01AB D6 .
0000 01AC E8 .
0000 01AD 42 B
0000 01AE 24 $
0000 01AF 47 G
-----------------------
0000 01B0 58 X
0000 01B1 33 3
0000 01B2 31 1
0000 01B3 12 .
0000 01B4 00 .
0000 01B5 E3 .
0000 01B6 F7 .
0000 01B7 CD .
0000 01B8 A9 .
0000 01B9 DD .
0000 01BA 65 e
0000 01BB D0 .
0000 01BC 17 .
0000 01BD 4D M
0000 01BE 6A J
0000 01BF 7E ~
------------------
0000 01C0 1F .
0000 01C1 CD .
0000 01C2 DF .
0000 01C3 B9 .
0000 01C4 DE .
0000 01C5 F6 .
0000 01C6 03 .
0000 01C7 4E N
0000 01C8 1C .
0000 01C9 FD .
0000 01CA CF .
0000 01CB 89 .
0000 01CC 25 %
0000 01CD E9 .
0000 01CE 47 G
0000 01CF FD .
----------------------
0000 01D0 B6 .
0000 01D1 35 5
0000 01D2 01 .
0000 01D3 8A .
0000 01D4 63 c
0000 01D5 22 "
0000 01D6 87 .
0000 01D7 5B [
0000 01D8 52 R
0000 01D9 0F .
0000 01DA 45 E
0000 01DB 23 #
0000 01DC 8B .
0000 01DD C3 .
0000 01DE A9 .
0000 01DF 30 0
-----------------------
0000 01E0 0D .
0000 01E1 B4 .
0000 01E2 D0 .
0000 01E3 FE .
0000 01E4 C1 .
0000 01E5 F2 .
0000 01E6 00 .
0000 01E7 F0 .
0000 01E8 71 q
0000 01E9 68 h
0000 01EA ED .
0000 01EB E6 .
0000 01EC 15 .
0000 01ED 04 .
0000 01EE DD .
0000 01EF 19 .
------------------
0000 01F0 2D -
0000 01F1 0A .
0000 01F2 9D .
0000 01F3 57 w
0000 01F4 22 "
0000 01F5 87 .
0000 01F6 99 .
0000 01F7 4C L
0000 01F8 80 .
0000 01F9 18 .
0000 01FA D7 .
0000 01FB 27 '
0000 01FC 2D -
0000 01FD 73 s
0000 01FE 27 '
0000 01FF 80 .
----------------------
0000 0200 2F /
0000 0201 C0 .
0000 0202 29 )
0000 0203 9E .
0000 0204 8F .
0000 0205 3D =
0000 0206 31 1
0000 0207 1D .
0000 0208 74 t
0000 0209 84 .
0000 020A 64 d
0000 020B 88 .
0000 020C 33 3
0000 020D 1D .
0000 020E 72 r
0000 020F 20
-----------------------
0000 0210 BB .
0000 0211 FC .
0000 0212 D6 .
0000 0213 2E .
0000 0214 26 &
0000 0215 A4 .
0000 0216 16 .
0000 0217 5C \
0000 0218 F8 .
0000 0219 54 T
0000 021A 6D m
0000 021B C5 .
0000 021C E2 .
0000 021D 4E N
0000 021E A3 .
0000 021F 41 A
------------------
0000 0220 EE .
0000 0221 12 .
0000 0222 38 8
0000 0223 1A .
0000 0224 F9 .
0000 0225 82 .
0000 0226 6E n
0000 0227 DC .
0000 0228 C5 .
0000 0229 7A z
0000 022A 79 y
0000 022B 02 .
0000 022C C5 .
0000 022D D9 .
0000 022E 74 t
0000 022F 3F ?
-----------------------
0000 0230 A4 .
0000 0231 3E >
0000 0232 66 f
0000 0233 36 6
0000 0234 4C L
0000 0235 BF .
0000 0236 B4 .
0000 0237 BD .
0000 0238 9A .
0000 0239 82 .
0000 023A 36 6
0000 023B 40 @
0000 023C 90 .
0000 023D 50 P
0000 023E 95 .
0000 023F F4 .
------------------
0000 0240 92 .
0000 0241 BD .
0000 0242 77 W
0000 0243 B9 .
0000 0244 17 .
0000 0245 A2 .
0000 0246 BE .
0000 0247 8E .
0000 0248 1B z
0000 0249 7A .
0000 024A 98 .
0000 024B 2C ,
0000 024C 1E .
0000 024D 8E .
0000 024E 16 .
0000 024F 6E N
----------------
0000 0250 AB .
0000 0251 CA .
0000 0252
0000 0253
0000 0254
0000 0255
0000 0256
0000 0257
0000 0258
0000 0259
0000 025A
0000 025B
0000 025C
0000 025D
0000 025E
0000 025F
jaynabonne wrote:Did you create the machine.bin file above by hand? If so, there might be a typo (if not, it's just odd). The 1A at 0x34 might be A1.
(BTW, that's some convoluted code there...)
jaynabonne wrote:Here's something to contemplate while looking through the code, as it might help to simplify it in your mind (since it does this a lot).
What is the effect of pairs of instructions like this?xor r2, r2
add r2, r1
jaynabonne wrote:Looks like a good plan! And keep in mind that there won't just be code in the .bin file. There will be data as well. For example, the first instruction is reading from offset 0x01a3, so you can be fairly sure that that will be a data byte and not a code byte.
So basically you shouldn't have to decode the entire file as instructions, assuming the code doesn't jump all over the place. You might only have to go as far as the HALT, if all the jnz's jump backwards (if that makes sense).
Edit: in fact, from around offset 0xab onward, it definitely looks like data for a while. (increasing integers from 0x0b to 0xff).
the xor zeros the (first:left) register (if both registers are the same), and then by adding a value to it, you're "setting" it to that new value.
var runner = {
execute: function(data) {
var ip = 0;
var r = [0,0,0,0,0,0];
var readByte = function() {
return data[ip++];
};
var readWord = function() {
return readByte()*256 + readByte();
};
var s = "";
var done = false;
var reg1, reg2, address;
while (!done) {
var opcode = readByte();
switch (opcode) {
case 0x11:
// ADD reg1 reg2 (reg1 = reg1 + reg2)
reg1 = readByte();
reg2 = readByte();
r[reg1] = (r[reg1] + r[reg2]) & 0x00ff;
break;
case 0x22:
// SUB reg1, reg2 (reg1 = reg1 - reg2
reg1 = readByte();
reg2 = readByte();
r[reg1] = (r[reg1] - r[reg2]) & 0x00ff;
break;
case 0x44:
// XOR reg1, reg2 (reg1 = reg1 ^ reg2
reg1 = readByte();
reg2 = readByte();
r[reg1] = r[reg1] ^ r[reg2];
break;
case 0x05:
// LOAD reg1, address (reg1 = [address]
reg1 = readByte();
address = readWord();
r[reg1] = data[address];
break;
case 0x55:
// LOADR reg1, address (reg1 = [address+reg1]
reg1 = readByte();
address = readWord();
r[reg1] = data[address + r[reg1]];
break;
case 0x06:
// STORE address ([address] = r0)
address = readWord();
data[address] = r[0];
break;
case 0x66:
// STORER reg1, address ([address+reg1] = r0)
reg1 = readByte();
address = readWord();
data[address + r[reg1]] = r[0];
break;
case 0xcc:
// OUT reg1 (output character in reg1)
reg1 = readByte();
s += String.fromCharCode(r[reg1]);
break;
case 0xaa:
// JNZ reg1, address
reg1 = readByte();
address = readWord();
if (r[reg1] !== 0)
ip = address;
break;
case 0xff:
done = true;
break;
}
}
return s;
}
};
var bin = [
0x05,0x04,0x01,0xA3,0x44,0x02,0x02,0x05,0x00,0x01,0xA0,0x05,0x04,0x01,0xA3,0x11,
0x00,0x04,0x06,0x01,0xA0,0x05,0x03,0x01,0xA1,0x44,0x01,0x01,0x11,0x01,0x00,0x55,
0x01,0x00,0xA0,0x11,0x03,0x01,0x44,0x05,0x05,0x11,0x05,0x00,0x44,0x00,0x00,0x11,
0x00,0x03,0x06,0x01,0xA1,0x44,0x00,0x00,0x11,0x00,0x05,0x44,0x01,0x01,0x11,0x01,
0x03,0x55,0x01,0x00,0xA0,0x44,0x05,0x05,0x11,0x05,0x01,0x44,0x01,0x01,0x11,0x01,
0x00,0x55,0x01,0x00,0xA0,0x44,0x04,0x04,0x11,0x04,0x00,0x44,0x00,0x00,0x11,0x00,
0x01,0x66,0x03,0x00,0xA0,0x44,0x00,0x00,0x11,0x00,0x05,0x66,0x04,0x00,0xA0,0x11,
0x01,0x05,0x55,0x01,0x00,0xA0,0x44,0x04,0x04,0x11,0x04,0x01,0x44,0x01,0x01,0x11,
0x01,0x02,0x55,0x01,0x01,0xA4,0x44,0x01,0x04,0xCC,0x01,0x05,0x04,0x01,0xA3,0x05,
0x05,0x01,0xA2,0x11,0x02,0x04,0x22,0x05,0x02,0xAA,0x05,0x00,0x07,0xFF,0x00,0x00,
0x63,0x06,0x37,0xA6,0x16,0x84,0xCC,0x71,0xE5,0x5A,0xCD,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x04,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x02,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x09,0x5B,0x5C,0x5D,0x5E,0x5F,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x70,0x07,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0x03,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0x01,0x0A,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
0x00,0x00,0xAE,0x01,0x8B,0x1B,0xFC,0x2F,0xA9,0xE0,0x11,0xD6,0xE8,0x42,0x24,0x47,
0x58,0x33,0x31,0x12,0x00,0xE3,0xF7,0xCD,0xA9,0xDD,0x65,0xD0,0x17,0x4D,0x6A,0x7E,
0x1F,0xCD,0xDF,0xB9,0xDE,0xF6,0x03,0x4E,0x1C,0xFD,0xCF,0x89,0x25,0xE9,0x47,0xFD,
0xB6,0x35,0x01,0x8A,0x63,0x22,0x87,0x5B,0x52,0x0F,0x45,0x23,0x8B,0xC3,0xA9,0x30,
0x0D,0xB4,0xD0,0xFE,0xC1,0xF2,0x00,0xF0,0x71,0x68,0xED,0xE6,0x15,0x04,0xDD,0x19,
0x2D,0x0A,0x9D,0x57,0x22,0x87,0x99,0x4C,0x80,0x18,0xD7,0x27,0x2D,0x73,0x27,0x80,
0x2F,0xC0,0x29,0x9E,0x8F,0x3D,0x31,0x1D,0x74,0x84,0x64,0x88,0x33,0x1D,0x72,0x20,
0xBB,0xFC,0xD6,0x2E,0x26,0xA4,0x16,0x5C,0xF8,0x54,0x6D,0xC5,0xE2,0x4E,0xA3,0x41,
0xEE,0x12,0x38,0x1A,0xF9,0x82,0x6E,0xDC,0xC5,0x7A,0x79,0x02,0xC5,0xD9,0x74,0x3F,
0xA4,0x3E,0x66,0x36,0x4C,0xBF,0xB4,0xBD,0x9A,0x82,0x36,0x40,0x90,0x50,0x95,0xF4,
0x92,0xBD,0x77,0xB9,0x17,0xA2,0xBE,0x8E,0x1B,0x7A,0x98,0x2C,0x1E,0x8E,0x16,0x6E,
0xAB,0xCA];
var result = runner.execute(bin);
console.log(result);
movzx edx, program_buffer[ebx]
movzx edx, word ptr program_buffer[ebx]
Size Dividend Divisor Quotient Remainder
byte AX r/m8 AL AH
word DX:AX r/m16 AX DX
dword EDX:EAX r/m32 EAX EDX
while N >= 10
store next digit: (N mod 10) + '0'
N = N /10
store last digit: (N mod 10) + '0'
;------------------------------------------------------------------------------
; HEADING
;------------------------------------------------------------------------------
; redacted
;------------------------------------------------------------------------------
; HISTORY
;------------------------------------------------------------------------------
; Version 1.0
;------------------------------------------------------------------------------
; PURPOSE
;------------------------------------------------------------------------------
; The purpose of this program is to emulate/parse a mathematical equation
;------------------------------------------------------------------------------
; MASM BUILD TYPE
;------------------------------------------------------------------------------
.586
;------------------------------------------------------------------------------
; MODEL, STANDARD, and Option TYPES
;------------------------------------------------------------------------------
.MODEL flat, stdcall
option casemap :none ;makes it case sensitive
;------------------------------------------------------------------------------
; LIBRARIES/MODULES
;------------------------------------------------------------------------------
;I had issues with trying to link to the "win32API.asm" file, (pasted it below)
;********************************************************
; Masm Include File for Windows 32-Bit API Functions
;
; The information contained in this file can be found at
; http://msdn.microsoft.com/en-us/library/default.aspx
;
;********************************************************
;********************************************************
; WINDOWS API FUNCTION PROTOTYPES
;********************************************************
ExitProcess PROTO : DWORD
GetStdHandle PROTO : DWORD
ReadConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
SetConsoleCursorPosition PROTO : DWORD, : DWORD
SetConsoleMode PROTO : DWORD, : DWORD
SetConsoleTextAttribute PROTO : DWORD, : DWORD
WriteConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
FlushConsoleInputBuffer PROTO : DWORD
CreateThread PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
CreateMutexA PROTO : DWORD, : DWORD, : DWORD
ReleaseMutex PROTO :DWORD
Sleep PROTO : DWORD
WaitForSingleObject PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD, :DWORD, :DWORD
SuspendThread PROTO : DWORD
ResumeThread PROTO : DWORD
ExitThread PROTO : DWORD
CreateFileA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
ReadFile PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
GetFileSize PROTO : DWORD, : DWORD
CloseHandle PROTO : DWORD
TIMECAPS Struct
wPeriodMin DWORD ?
wPeriodMax DWORD ?
TIMECAPS Ends
timeGetDevCaps PROTO : DWORD, : DWORD
timeBeginPeriod PROTO : DWORD
timeGetTime PROTO
GetTickCount PROTO
QueryPerformanceCounter PROTO : DWORD
QueryPerformanceFrequency PROTO : DWORD
GetLastError PROTO
;********************************************************
; EQUATES
;********************************************************
NULL EQU 0
;*****************************************************
; Standard Handles
;*****************************************************
STD_INPUT_HANDLE EQU -10 ;Standard Input Handle
STD_OUTPUT_HANDLE EQU -11 ;Standard Output Handle
STD_ERROR_HANDLE EQU -12 ;Standard Error Handle
GENERIC_ALL EQU 10000000h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
FILE_SHARE_NONE EQU 0
FILE_SHARE_DELETE EQU 4
FILE_SHARE_READ EQU 1
FILE_SHARE_WRITE EQU 2
CREATE_NEW EQU 1
CREATE_ALWAYS EQU 2
OPEN_EXISTING EQU 3
OPEN_ALWAYS EQU 4
TRUNCATE_EXISTING EQU 5
FILE_ATTRIBUTE_NORMAL EQU 80h
;*****************************************************
; Set Console Mode Equates
;
; Refer to Microsoft's documentation on SetConsoleMode
; for a complete description of these equates.
;*****************************************************
ENABLE_NOTHING_INPUT EQU 0000h ;Turn off all input options
ENABLE_ECHO_INPUT EQU 0004h ;Characters read are written to the active screen buffer (can be used with ENABLE_LINE_INPUT)
ENABLE_INSERT_MODE EQU 0020h ;When enabled, text entered in a console window will be inserted at the current cursor location
ENABLE_LINE_INPUT EQU 0002h ;The ReadConsole function returns only when a carriage return character is read.
ENABLE_MOUSE_INPUT EQU 0010h ;If the mouse is within the borders of the console window & the window has the keyboard focus, mouse events are placed in the input buffer. These events are discarded by ReadFile or ReadConsole.
ENABLE_PROCESSED_INPUT EQU 0001h ;CTRL+C is processed by the system and is not placed in the input buffer.
ENABLE_QUICK_EDIT_MODE EQU 0040h ;This flag enables the user to use the mouse to select and edit text. To enable this option, use the OR to combine this flag with ENABLE_EXTENDED_FLAGS.
ENABLE_WINDOW_INPUT EQU 0008h ;User interactions that change the size of the console screen buffer are reported in the console's input buffer.
;If the hConsoleHandle parameter is a screen buffer handle, the mode can be one or more of the following values. When a screen buffer is created, both output modes are enabled by default.
ENABLE_PROCESSED_OUTPUT EQU 0001h ;Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or ReadConsole function are examined for ASCII control sequences and the correct action is performed.
ENABLE_WRAP_AT_EOL_OUTPUT EQU 0002h ;When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the cursor moves to the beginning of the next row when it reaches the end of the current row.
;********************************************************
; CONSOLE FOREGROUND AND BACKGROUND COLOR EQUATES
;********************************************************
FOREGROUND_BLACK EQU 0
FOREGROUND_DARK_BLUE EQU 1
FOREGROUND_DARK_GREEN EQU 2
FOREGROUND_DARK_CYAN EQU 3
FOREGROUND_DARK_RED EQU 4
FOREGROUND_DARK_MAGENTA EQU 5
FOREGROUND_DARK_YELLOW EQU 6
FOREGROUND_GRAY EQU 7
FOREGROUND_DARK_GRAY EQU 8
FOREGROUND_BLUE EQU 9
FOREGROUND_GREEN EQU 10
FOREGROUND_CYAN EQU 11
FOREGROUND_RED EQU 12
FOREGROUND_MAGENTA EQU 13
FOREGROUND_YELLOW EQU 14
FOREGROUND_WHITE EQU 15
BACKGROUND_BLACK EQU FOREGROUND_BLACK * 10h
BACKGROUND_DARK_BLUE EQU FOREGROUND_DARK_BLUE * 10h
BACKGROUND_DARK_GREEN EQU FOREGROUND_DARK_GREEN * 10h
BACKGROUND_DARK_CYAN EQU FOREGROUND_DARK_CYAN * 10h
BACKGROUND_DARK_RED EQU FOREGROUND_DARK_RED * 10h
BACKGROUND_DARK_MAGENTA EQU FOREGROUND_DARK_MAGENTA * 10h
BACKGROUND_DARK_YELLOW EQU FOREGROUND_DARK_YELLOW * 10h
BACKGROUND_GRAY EQU FOREGROUND_GRAY * 10h
BACKGROUND_DARK_GRAY EQU FOREGROUND_DARK_GRAY * 10h
BACKGROUND_BLUE EQU FOREGROUND_BLUE * 10h
BACKGROUND_GREEN EQU FOREGROUND_GREEN * 10h
BACKGROUND_CYAN EQU FOREGROUND_CYAN * 10h
BACKGROUND_RED EQU FOREGROUND_RED * 10h
BACKGROUND_MAGENTA EQU FOREGROUND_MAGENTA * 10h
BACKGROUND_YELLOW EQU FOREGROUND_YELLOW * 10h
BACKGROUND_WHITE EQU FOREGROUND_WHITE * 10h
;------------------------------------------------------------------------------
; STACK SIZE
;------------------------------------------------------------------------------
.STACK 4096
;------------------------------------------------------------------------------
; RADIX TYPE
;------------------------------------------------------------------------------
; (placeholder)
;------------------------------------------------------------------------------
; DATA SEGMENT (DS)
;------------------------------------------------------------------------------
.DATA
;*********************
; EQUATES/ENUMERATORS
;*********************
CARRIAGE_RETURN EQU 0Dh
NEW_LINE_FEED EQU 0Ah
NULL_POINTER EQU 00h
INPUT_BUFFER_SIZE EQU 1Bh
OUTPUT_BUFFER_SIZE EQU 29h
SPACE EQU 20h
QUESTION_MARK EQU 3Fh
EQUAL EQU 3Dh
NEGATIVE EQU 2Dh
ADDITION EQU 2Bh
SUBTRACTION EQU 2Dh
MULTIPLICATION EQU 2Ah
DIVISON EQU 2Ch
ZERO EQU 30h
ONE EQU 31h
TWO EQU 32h
THREE EQU 33h
FOUR EQU 34h
FIVE EQU 35h
SIX EQU 36h
SEVEN EQU 37h
EIGHT EQU 38h
NINE EQU 39h
RETURN_ERROR EQU 01h
;***********
; VARIABLES
;***********
heading byte "redacted", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
history byte "Version 1.0", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
purpose byte "This program's purpose is to evaluate/parse",\
" a mathematical equation", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
input_prompt byte "Enter a mathematical equation in the form of"\
", <value(space)operation(space)value> , : ", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
output_prompt byte CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED,\
"The result is:", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
division_by_zero byte "Error: Division by zero, result is undefined"\
, CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
overflow_flagged byte "Overflow occurred", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
underflow_flagged byte "Underflow occurred", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
input_buffer byte INPUT_BUFFER_SIZE dup (QUESTION_MARK)
output_buffer byte OUTPUT_BUFFER_SIZE dup (QUESTION_MARK)
operand_1 sdword QUESTION_MARK
operand_2 sdword QUESTION_MARK
result_value sdword QUESTION_MARK
return_code dword NULL_POINTER
bytes_written dword QUESTION_MARK
bytes_read dword QUESTION_MARK
handle_standard_out dword QUESTION_MARK
handle_standard_in dword QUESTION_MARK
;------------------------------------------------------------------------------
; CODE SEGMENT (CS)
;------------------------------------------------------------------------------
.CODE
Main Proc
;*******************************
; Get handle to standard output
;*******************************
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov handle_stardard_out, eax
;******************************
; Get handle to standard input
;******************************
invoke GetStdHandle, STD_INPUT_HANDLE
mov handle_standard_in, eax
;**************
; Program Info
;**************
invoke WriteConsoleA, handle_standard_out, offset heading, \
sizeof heading, offset bytes_written, NULL_POINTER
invoke WriteConsoleA, handle_standard_out, offset history, \
sizeof history, offset bytes_written, NULL_POINTER
invoke WriteConsoleA, handle_standard_out, offset purpose, \
sizeof heading, offset bytes_written, NULL_POINTER
;***********************
; Prompt for User Input
;***********************
invoke WriteConsoleA, handle_standard_out, offset input_prompt, \
sizeof input_prompt, offset bytes_written, NULL_POINTER
;****************
; Get User Input
;****************
invoke ReadConsoleA, handle_standard_in, offset input_buffer, \
sizeof input_buffer, offset bytes_read, NULL_POINTER
;*********
; Program
;*********
Pre_Start:
mov esi, offset input_buffer
movzx ebp, byte ptr bytes_read
mov edi, offset output_buffer
movzx edx, OUTPUT_BUFFER_SIZE
xor eax, eax
xor ebx, ebx
xor ecx, ecx
Get_Operand_Size:
cmp esi[ebx], SPACE
je Set_Operand_Size
add ebx, byte ptr ONE
jmp Get_Operand_Size
Set_Operand_Size:
movzx ecx, ebx
Start:
call ASCII_To_Decimal (esi, ecx)
Addition:
adc operand_1, operand_2
Subtraction:
sbb operand_1, operand_2
Multiplication:
imul operand_1, operand_2
Division:
cmp operand_2, ZERO
je Division_By_Zero
idiv operand_1, operand_2
;***********************
; Display Output Prompt
;***********************
invoke WriteConsoleA, handle_standard_out, offset output_prompt, \
sizeof output_prompt, offset bytes_written, NULL_POINTER
;****************
; Display Output
;****************
invoke WriteConsoleA, handle_standard_out, offset output_buffer, \
sizeof xxx, offset bytes_written, NULL_POINTER
Invalid_Input:
movzx return_code, RETURN_ERROR
Finish:
invoke ExitProcess, return_code
Main endp
ASCII_To_Decimal proc stdcall uses ebx ecx edx esi edi ebp,
local sign_value byte ZERO
local Pre_Start_ASCII_To_Decimal:
cmp byte ptr [esi], ZERO
je Invalid_Input
cmp byte ptr [esi], NINE
je Invalid_Input
movzx edx, byte ptr eax
sub edx, ZERO
add eax, edx
local Start_ASCII_To_Decimal:
cmp ecx, ZERO
je Sign_ASCII_To_Decimal
movzx edx, eax
shl eax, byte ptr THREE
add eax, edx
add eax, edx
movzx edx, byte ptr esi[-ecx]
sub edx, ZERO
add eax, edx
sub ecx, byte ptr ONE
jmp Start_ASCII_To_Decimal
local Sign_ASCII_To_Decimal:
cmp esi[ebx], SIGN
jne Finish_ASCII_To_Decimal
neg eax
local Finish_ASCII_To_Decimal:
ret
ASCII_To_Decimal endp
Decimal_To_ASCII proc stdcall uses eax ebx edx esi edi ebp,
ret
Decimal_To_ASCII endp
end Main
add ebx, byte ptr ONE
cmp byte ptr [esi], ZERO
je Invalid_Input
cmp byte ptr [esi], NINE
je Invalid_Input
shl eax, byte ptr THREE
...
sub ecx, byte ptr ONE
movzx edx, byte ptr eax
sub edx, ZERO
add eax, edx
local Start_ASCII_To_Decimal:
cmp esi[ebx], SIGN
;------------------------------------------------------------------------------
; HEADING
;------------------------------------------------------------------------------
; redacted
;------------------------------------------------------------------------------
; HISTORY
;------------------------------------------------------------------------------
; Version 1.0
;------------------------------------------------------------------------------
; PURPOSE
;------------------------------------------------------------------------------
; The purpose of this program is to emulate/parse a mathematical equation
;------------------------------------------------------------------------------
; MASM BUILD TYPE
;------------------------------------------------------------------------------
.586
;------------------------------------------------------------------------------
; MODEL, STANDARD, and Option TYPES
;------------------------------------------------------------------------------
.MODEL flat, stdcall
option casemap :none ;makes it case sensitive
;------------------------------------------------------------------------------
; LIBRARIES/MODULES
;------------------------------------------------------------------------------
;I had issues with trying to link to the "win32API.asm" file, (pasted it below)
;********************************************************
; Masm Include File for Windows 32-Bit API Functions
;
; The information contained in this file can be found at
; http://msdn.microsoft.com/en-us/library/default.aspx
;
;********************************************************
;********************************************************
; WINDOWS API FUNCTION PROTOTYPES
;********************************************************
ExitProcess PROTO : DWORD
GetStdHandle PROTO : DWORD
ReadConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
SetConsoleCursorPosition PROTO : DWORD, : DWORD
SetConsoleMode PROTO : DWORD, : DWORD
SetConsoleTextAttribute PROTO : DWORD, : DWORD
WriteConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
FlushConsoleInputBuffer PROTO : DWORD
CreateThread PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
CreateMutexA PROTO : DWORD, : DWORD, : DWORD
ReleaseMutex PROTO :DWORD
Sleep PROTO : DWORD
WaitForSingleObject PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD, :DWORD, :DWORD
SuspendThread PROTO : DWORD
ResumeThread PROTO : DWORD
ExitThread PROTO : DWORD
CreateFileA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
ReadFile PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
GetFileSize PROTO : DWORD, : DWORD
CloseHandle PROTO : DWORD
TIMECAPS Struct
wPeriodMin DWORD ?
wPeriodMax DWORD ?
TIMECAPS Ends
timeGetDevCaps PROTO : DWORD, : DWORD
timeBeginPeriod PROTO : DWORD
timeGetTime PROTO
GetTickCount PROTO
QueryPerformanceCounter PROTO : DWORD
QueryPerformanceFrequency PROTO : DWORD
GetLastError PROTO
;********************************************************
; EQUATES
;********************************************************
NULL EQU 0
;*****************************************************
; Standard Handles
;*****************************************************
STD_INPUT_HANDLE EQU -10 ;Standard Input Handle
STD_OUTPUT_HANDLE EQU -11 ;Standard Output Handle
STD_ERROR_HANDLE EQU -12 ;Standard Error Handle
GENERIC_ALL EQU 10000000h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
FILE_SHARE_NONE EQU 0
FILE_SHARE_DELETE EQU 4
FILE_SHARE_READ EQU 1
FILE_SHARE_WRITE EQU 2
CREATE_NEW EQU 1
CREATE_ALWAYS EQU 2
OPEN_EXISTING EQU 3
OPEN_ALWAYS EQU 4
TRUNCATE_EXISTING EQU 5
FILE_ATTRIBUTE_NORMAL EQU 80h
;*****************************************************
; Set Console Mode Equates
;
; Refer to Microsoft's documentation on SetConsoleMode
; for a complete description of these equates.
;*****************************************************
ENABLE_NOTHING_INPUT EQU 0000h ;Turn off all input options
ENABLE_ECHO_INPUT EQU 0004h ;Characters read are written to the active screen buffer (can be used with ENABLE_LINE_INPUT)
ENABLE_INSERT_MODE EQU 0020h ;When enabled, text entered in a console window will be inserted at the current cursor location
ENABLE_LINE_INPUT EQU 0002h ;The ReadConsole function returns only when a carriage return character is read.
ENABLE_MOUSE_INPUT EQU 0010h ;If the mouse is within the borders of the console window & the window has the keyboard focus, mouse events are placed in the input buffer. These events are discarded by ReadFile or ReadConsole.
ENABLE_PROCESSED_INPUT EQU 0001h ;CTRL+C is processed by the system and is not placed in the input buffer.
ENABLE_QUICK_EDIT_MODE EQU 0040h ;This flag enables the user to use the mouse to select and edit text. To enable this option, use the OR to combine this flag with ENABLE_EXTENDED_FLAGS.
ENABLE_WINDOW_INPUT EQU 0008h ;User interactions that change the size of the console screen buffer are reported in the console's input buffer.
;If the hConsoleHandle parameter is a screen buffer handle, the mode can be one or more of the following values. When a screen buffer is created, both output modes are enabled by default.
ENABLE_PROCESSED_OUTPUT EQU 0001h ;Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or ReadConsole function are examined for ASCII control sequences and the correct action is performed.
ENABLE_WRAP_AT_EOL_OUTPUT EQU 0002h ;When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the cursor moves to the beginning of the next row when it reaches the end of the current row.
;********************************************************
; CONSOLE FOREGROUND AND BACKGROUND COLOR EQUATES
;********************************************************
FOREGROUND_BLACK EQU 0
FOREGROUND_DARK_BLUE EQU 1
FOREGROUND_DARK_GREEN EQU 2
FOREGROUND_DARK_CYAN EQU 3
FOREGROUND_DARK_RED EQU 4
FOREGROUND_DARK_MAGENTA EQU 5
FOREGROUND_DARK_YELLOW EQU 6
FOREGROUND_GRAY EQU 7
FOREGROUND_DARK_GRAY EQU 8
FOREGROUND_BLUE EQU 9
FOREGROUND_GREEN EQU 10
FOREGROUND_CYAN EQU 11
FOREGROUND_RED EQU 12
FOREGROUND_MAGENTA EQU 13
FOREGROUND_YELLOW EQU 14
FOREGROUND_WHITE EQU 15
BACKGROUND_BLACK EQU FOREGROUND_BLACK * 10h
BACKGROUND_DARK_BLUE EQU FOREGROUND_DARK_BLUE * 10h
BACKGROUND_DARK_GREEN EQU FOREGROUND_DARK_GREEN * 10h
BACKGROUND_DARK_CYAN EQU FOREGROUND_DARK_CYAN * 10h
BACKGROUND_DARK_RED EQU FOREGROUND_DARK_RED * 10h
BACKGROUND_DARK_MAGENTA EQU FOREGROUND_DARK_MAGENTA * 10h
BACKGROUND_DARK_YELLOW EQU FOREGROUND_DARK_YELLOW * 10h
BACKGROUND_GRAY EQU FOREGROUND_GRAY * 10h
BACKGROUND_DARK_GRAY EQU FOREGROUND_DARK_GRAY * 10h
BACKGROUND_BLUE EQU FOREGROUND_BLUE * 10h
BACKGROUND_GREEN EQU FOREGROUND_GREEN * 10h
BACKGROUND_CYAN EQU FOREGROUND_CYAN * 10h
BACKGROUND_RED EQU FOREGROUND_RED * 10h
BACKGROUND_MAGENTA EQU FOREGROUND_MAGENTA * 10h
BACKGROUND_YELLOW EQU FOREGROUND_YELLOW * 10h
BACKGROUND_WHITE EQU FOREGROUND_WHITE * 10h
;------------------------------------------------------------------------------
; STACK SIZE
;------------------------------------------------------------------------------
.STACK 4096
;------------------------------------------------------------------------------
; RADIX TYPE
;------------------------------------------------------------------------------
; (placeholder)
;------------------------------------------------------------------------------
; DATA SEGMENT (DS)
;------------------------------------------------------------------------------
.DATA
;*********************
; EQUATES/ENUMERATORS
;*********************
CARRIAGE_RETURN EQU 0Dh
NEW_LINE_FEED EQU 0Ah
NULL_POINTER EQU 00h
MAX_INPUT_BUFFER_SIZE EQU 1Bh
MAX_OUTPUT_BUFFER_SIZE EQU 29h
SPACE EQU 20h
EQUAL EQU 3Dh
NEGATIVE EQU 2Dh
ADDITION EQU 2Bh
SUBTRACTION EQU 2Dh
MULTIPLICATION EQU 2Ah
DIVISON EQU 2Ch
ZERO_ASCII EQU 30h
RETURN_ERROR EQU 01h
;***********
; VARIABLES
;***********
heading byte "redacted",
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
history byte "Version 1.0", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
purpose byte "This program's purpose is to evaluate/parse",\
" a mathematical equation", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
input_prompt byte "Enter a mathematical equation in the form of"\
", <value(space)operation(space)value> , : ", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
output_prompt byte CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED,\
"The result is:", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
division_by_zero byte "Error: Division by zero, result is undefined"\
, CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
overflow_flagged byte "Overflow occurred", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
underflow_flagged byte "Underflow occurred", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
input_buffer byte INPUT_BUFFER_SIZE dup (?)
output_buffer byte OUTPUT_BUFFER_SIZE dup (?)
operand_1 sdword ?
operand_2 sdword ?
result_value sdword ?
return_code dword 00h
bytes_read dword ?
bytes_written dword ?
handle_standard_out dword ?
handle_standard_in dword ?
;------------------------------------------------------------------------------
; CODE SEGMENT (CS)
;------------------------------------------------------------------------------
.CODE
Main Proc
;*******************************
; Get handle to standard output
;*******************************
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov handle_stardard_out, eax
;******************************
; Get handle to standard input
;******************************
invoke GetStdHandle, STD_INPUT_HANDLE
mov handle_standard_in, eax
;**************
; Program Info
;**************
invoke WriteConsoleA, handle_standard_out, offset heading, \
sizeof heading, offset bytes_written, NULL_POINTER
invoke WriteConsoleA, handle_standard_out, offset history, \
sizeof history, offset bytes_written, NULL_POINTER
invoke WriteConsoleA, handle_standard_out, offset credit, \
sizeof credit, offset bytes_written, NULL_POINTER
invoke WriteConsoleA, handle_standard_out, offset purpose, \
sizeof heading, offset bytes_written, NULL_POINTER
;***********************
; Prompt for User Input
;***********************
invoke WriteConsoleA, handle_standard_out, offset input_prompt, \
sizeof input_prompt, offset bytes_written, NULL_POINTER
;****************
; Get User Input
;****************
invoke ReadConsoleA, handle_standard_in, offset input_buffer, \
sizeof input_buffer, offset bytes_read, NULL_POINTER
;*********
; Program
;*********
Pre_Start:
mov esi, offset input_buffer
movzx ebp, bytes_read
mov edi, offset output_buffer
movzx edx, OUTPUT_BUFFER_SIZE
xor eax, eax
xor ebx, ebx
xor ecx, ecx
Get_Operand_Size:
cmp esi[ebx], SPACE
je Set_Operand_Size
cmp esi[ebx], CARRIAGE_RETURN
je Set_Operand_Size
add ebx, 01h
jmp Get_Operand_Size
Set_Operand_Size:
movzx ecx, ebx
Start:
call ASCII_To_Decimal (esi, ecx)
movzx operand_1, eax
add ebx, 01h
jnp Get_Operand_Size
; need to handle getting operator
; need to handle getting operand_2
Addition:
adc operand_1, operand_2
Subtraction:
sbb operand_1, operand_2
Multiplication:
imul operand_1, operand_2
Division:
cmp operand_2, 00h
je Division_By_Zero
idiv operand_1, operand_2
;***********************
; Display Output Prompt
;***********************
invoke WriteConsoleA, handle_standard_out, offset output_prompt, \
sizeof output_prompt, offset bytes_written, NULL_POINTER
;****************
; Display Output
;****************
invoke WriteConsoleA, handle_standard_out, offset output_buffer, \
sizeof output_buffer, offset bytes_written, NULL_POINTER
Invalid_Input:
movzx return_code, RETURN_ERROR
Finish:
invoke ExitProcess, return_code
Main endp
ASCII_To_Decimal proc stdcall uses ebx ecx edx esi edi ebp,
local Pre_Start_ASCII_To_Decimal:
xor ebx, ebx
cmp esi[ebx], SIGN
je Sign_To_Zero_ASCII_To_Decimal
cmp byte ptr esi[ebx], 00h
jb Invalid_Input
cmp byte ptr esi[ebx], 09h
ja Invalid_Input
movzx edx, byte ptr esi[ebx]
sub edx, ZERO_CHAR
add eax, edx
add ebx, 01h
local Start_ASCII_To_Decimal:
cmp ecx, 00h
je Is_Sign_ASCII_To_Decimal
movzx edx, eax
shl eax, 03h
add eax, edx
add eax, edx
movzx edx, byte ptr esi[ebx]
sub edx, ZERO_CHAR
add eax, edx
add ebx, 01h
sub ecx, 01h
jmp Start_ASCII_To_Decimal
local Sign_To_Zero_ASCII_To_Decimal:
movzx edx, byte ptr eax
sub edx, ZERO_ASCII
add eax, edx
add ebx, 01h
jmp Start_ASCII_To_Decimal
local Is_Sign_ASCII_To_Decimal:
cmp esi[01h], SIGN
jne Finish_ASCII_To_Decimal
neg eax
local Finish_ASCII_To_Decimal:
ret
ASCII_To_Decimal endp
Decimal_To_ASCII proc stdcall uses eax ebx edx esi edi ebp,
ret
Decimal_To_ASCII endp
end Main
movzx edx, byte ptr esi[ebx]
sub edx, ZERO_CHAR
add eax, edx
add ebx, 01h
;------------------------------------------------------------------------------
; HEADING
;------------------------------------------------------------------------------
; redacted
;------------------------------------------------------------------------------
; HISTORY
;------------------------------------------------------------------------------
; Version 1.0
;------------------------------------------------------------------------------
; PURPOSE
;------------------------------------------------------------------------------
; The purpose of this program is to emulate/parse a mathematical equation
;------------------------------------------------------------------------------
; MASM BUILD TYPE
;------------------------------------------------------------------------------
.586
;------------------------------------------------------------------------------
; MODEL, STANDARD, and Option TYPES
;------------------------------------------------------------------------------
.MODEL flat, stdcall
option casemap :none ;makes it case sensitive
;------------------------------------------------------------------------------
; LIBRARIES/MODULES
;------------------------------------------------------------------------------
;I had issues with trying to link to the "win32API.asm" file, (pasted it below)
;********************************************************
; Masm Include File for Windows 32-Bit API Functions
;
; The information contained in this file can be found at
; http://msdn.microsoft.com/en-us/library/default.aspx
;
;********************************************************
;********************************************************
; WINDOWS API FUNCTION PROTOTYPES
;********************************************************
ExitProcess PROTO : DWORD
GetStdHandle PROTO : DWORD
ReadConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
SetConsoleCursorPosition PROTO : DWORD, : DWORD
SetConsoleMode PROTO : DWORD, : DWORD
SetConsoleTextAttribute PROTO : DWORD, : DWORD
WriteConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
FlushConsoleInputBuffer PROTO : DWORD
CreateThread PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
CreateMutexA PROTO : DWORD, : DWORD, : DWORD
ReleaseMutex PROTO :DWORD
Sleep PROTO : DWORD
WaitForSingleObject PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD, :DWORD, :DWORD
SuspendThread PROTO : DWORD
ResumeThread PROTO : DWORD
ExitThread PROTO : DWORD
CreateFileA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
ReadFile PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
GetFileSize PROTO : DWORD, : DWORD
CloseHandle PROTO : DWORD
TIMECAPS Struct
wPeriodMin DWORD ?
wPeriodMax DWORD ?
TIMECAPS Ends
timeGetDevCaps PROTO : DWORD, : DWORD
timeBeginPeriod PROTO : DWORD
timeGetTime PROTO
GetTickCount PROTO
QueryPerformanceCounter PROTO : DWORD
QueryPerformanceFrequency PROTO : DWORD
GetLastError PROTO
;********************************************************
; EQUATES
;********************************************************
NULL EQU 0
;*****************************************************
; Standard Handles
;*****************************************************
STD_INPUT_HANDLE EQU -10 ;Standard Input Handle
STD_OUTPUT_HANDLE EQU -11 ;Standard Output Handle
STD_ERROR_HANDLE EQU -12 ;Standard Error Handle
GENERIC_ALL EQU 10000000h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
FILE_SHARE_NONE EQU 0
FILE_SHARE_DELETE EQU 4
FILE_SHARE_READ EQU 1
FILE_SHARE_WRITE EQU 2
CREATE_NEW EQU 1
CREATE_ALWAYS EQU 2
OPEN_EXISTING EQU 3
OPEN_ALWAYS EQU 4
TRUNCATE_EXISTING EQU 5
FILE_ATTRIBUTE_NORMAL EQU 80h
;*****************************************************
; Set Console Mode Equates
;
; Refer to Microsoft's documentation on SetConsoleMode
; for a complete description of these equates.
;*****************************************************
ENABLE_NOTHING_INPUT EQU 0000h ;Turn off all input options
ENABLE_ECHO_INPUT EQU 0004h ;Characters read are written to the active screen buffer (can be used with ENABLE_LINE_INPUT)
ENABLE_INSERT_MODE EQU 0020h ;When enabled, text entered in a console window will be inserted at the current cursor location
ENABLE_LINE_INPUT EQU 0002h ;The ReadConsole function returns only when a carriage return character is read.
ENABLE_MOUSE_INPUT EQU 0010h ;If the mouse is within the borders of the console window & the window has the keyboard focus, mouse events are placed in the input buffer. These events are discarded by ReadFile or ReadConsole.
ENABLE_PROCESSED_INPUT EQU 0001h ;CTRL+C is processed by the system and is not placed in the input buffer.
ENABLE_QUICK_EDIT_MODE EQU 0040h ;This flag enables the user to use the mouse to select and edit text. To enable this option, use the OR to combine this flag with ENABLE_EXTENDED_FLAGS.
ENABLE_WINDOW_INPUT EQU 0008h ;User interactions that change the size of the console screen buffer are reported in the console's input buffer.
;If the hConsoleHandle parameter is a screen buffer handle, the mode can be one or more of the following values. When a screen buffer is created, both output modes are enabled by default.
ENABLE_PROCESSED_OUTPUT EQU 0001h ;Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or ReadConsole function are examined for ASCII control sequences and the correct action is performed.
ENABLE_WRAP_AT_EOL_OUTPUT EQU 0002h ;When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the cursor moves to the beginning of the next row when it reaches the end of the current row.
;********************************************************
; CONSOLE FOREGROUND AND BACKGROUND COLOR EQUATES
;********************************************************
FOREGROUND_BLACK EQU 0
FOREGROUND_DARK_BLUE EQU 1
FOREGROUND_DARK_GREEN EQU 2
FOREGROUND_DARK_CYAN EQU 3
FOREGROUND_DARK_RED EQU 4
FOREGROUND_DARK_MAGENTA EQU 5
FOREGROUND_DARK_YELLOW EQU 6
FOREGROUND_GRAY EQU 7
FOREGROUND_DARK_GRAY EQU 8
FOREGROUND_BLUE EQU 9
FOREGROUND_GREEN EQU 10
FOREGROUND_CYAN EQU 11
FOREGROUND_RED EQU 12
FOREGROUND_MAGENTA EQU 13
FOREGROUND_YELLOW EQU 14
FOREGROUND_WHITE EQU 15
BACKGROUND_BLACK EQU FOREGROUND_BLACK * 10h
BACKGROUND_DARK_BLUE EQU FOREGROUND_DARK_BLUE * 10h
BACKGROUND_DARK_GREEN EQU FOREGROUND_DARK_GREEN * 10h
BACKGROUND_DARK_CYAN EQU FOREGROUND_DARK_CYAN * 10h
BACKGROUND_DARK_RED EQU FOREGROUND_DARK_RED * 10h
BACKGROUND_DARK_MAGENTA EQU FOREGROUND_DARK_MAGENTA * 10h
BACKGROUND_DARK_YELLOW EQU FOREGROUND_DARK_YELLOW * 10h
BACKGROUND_GRAY EQU FOREGROUND_GRAY * 10h
BACKGROUND_DARK_GRAY EQU FOREGROUND_DARK_GRAY * 10h
BACKGROUND_BLUE EQU FOREGROUND_BLUE * 10h
BACKGROUND_GREEN EQU FOREGROUND_GREEN * 10h
BACKGROUND_CYAN EQU FOREGROUND_CYAN * 10h
BACKGROUND_RED EQU FOREGROUND_RED * 10h
BACKGROUND_MAGENTA EQU FOREGROUND_MAGENTA * 10h
BACKGROUND_YELLOW EQU FOREGROUND_YELLOW * 10h
BACKGROUND_WHITE EQU FOREGROUND_WHITE * 10h
;------------------------------------------------------------------------------
; STACK SIZE
;------------------------------------------------------------------------------
.STACK 4096
;------------------------------------------------------------------------------
; RADIX TYPE
;------------------------------------------------------------------------------
; (placeholder)
;------------------------------------------------------------------------------
; DATA SEGMENT (DS)
;------------------------------------------------------------------------------
.DATA
;*********************
; EQUATES/ENUMERATORS
;*********************
CARRIAGE_RETURN EQU 0Dh
NEW_LINE_FEED EQU 0Ah
NULL_POINTER EQU 00h
MAX_INPUT_BUFFER_SIZE EQU 1Bh
MAX_OUTPUT_BUFFER_SIZE EQU 29h
SPACE EQU 20h
EQUAL EQU 3Dh
NEGATIVE EQU 2Dh
ADDITION EQU 2Bh
SUBTRACTION EQU 2Dh
MULTIPLICATION EQU 2Ah
DIVISON EQU 2Ch
ZERO_ASCII EQU 30h
RETURN_ERROR EQU 01h
;***********
; VARIABLES
;***********
heading byte "redacted",
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
history byte "Version 1.0", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
purpose byte "This program's purpose is to evaluate/parse",\
" a mathematical equation", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
input_prompt byte "Enter a mathematical equation in the form of"\
", <value(space)operation(space)value> , : ", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
output_prompt byte CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED,\
"The result is:", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
division_by_zero byte "Error: Division by zero, result is undefined"\
, CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
overflow_flagged byte "Overflow occurred", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
underflow_flagged byte "Underflow occurred", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
input_buffer byte INPUT_BUFFER_SIZE dup (?)
output_buffer byte OUTPUT_BUFFER_SIZE dup (?)
operator_variable byte ?
operand_1 sdword ?
operand_2 sdword ?
result_value sdword ?
return_code dword 00h
bytes_read dword ?
bytes_written dword ?
handle_standard_out dword ?
handle_standard_in dword ?
;------------------------------------------------------------------------------
; CODE SEGMENT (CS)
;------------------------------------------------------------------------------
.CODE
Main Proc
;*******************************
; Get handle to standard output
;*******************************
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov handle_stardard_out, eax
;******************************
; Get handle to standard input
;******************************
invoke GetStdHandle, STD_INPUT_HANDLE
mov handle_standard_in, eax
;**************
; Program Info
;**************
invoke WriteConsoleA, handle_standard_out, offset heading, \
sizeof heading, offset bytes_written, NULL_POINTER
invoke WriteConsoleA, handle_standard_out, offset history, \
sizeof history, offset bytes_written, NULL_POINTER
invoke WriteConsoleA, handle_standard_out, offset purpose, \
sizeof heading, offset bytes_written, NULL_POINTER
;***********************
; Prompt for User Input
;***********************
invoke WriteConsoleA, handle_standard_out, offset input_prompt, \
sizeof input_prompt, offset bytes_written, NULL_POINTER
;****************
; Get User Input
;****************
invoke ReadConsoleA, handle_standard_in, offset input_buffer, \
sizeof input_buffer, offset bytes_read, NULL_POINTER
;*********
; Program
;*********
Pre_Start:
mov esi, offset input_buffer
mov edi, offset output_buffer
movzx edx, OUTPUT_BUFFER_SIZE
xor ebx, ebx
xor ecx, ecx
Start:
xor eax, eax
Get_Operand_Length:
cmp byte ptr esi[ebx], SPACE
je Set_Operand_1_Length
cmp byte ptr esi[ebx], CARRIAGE_RETURN
je Set_Operand_2_Length
add ebx, 01h
jmp Get_Operand_Length
Set_Operand_1_Length:
movzx ecx, ebx
sub ecx, ebp
Operand_1:
call ASCII_To_Decimal (esi, ecx)
movzx operand_1, eax
movzx ebp, ebx
Skip_To_Operator:
add ebx, 02h
Store_Operator:
movzx operator_variable, byte ptr esi[ebx]
Skip_Past_Operator_To_Handling_Operand_2:
add ebx, 02h
jnp Start
Set_Operand_2_Length:
movzx ecx, ebx
sub ecx, ebp
Operand_2:
call ASCII_To_Decimal (esi, ecx)
movzx operand_2, eax
movzx ebp, ebx
Determining_Arithmetic_Operation:
movzx ebp, operator_variable
cmp ebp, ADDITION
je Addition
cmp ebp, SUBTRACTION
je Subtraction
cmp ebp, MULTIPLICATION
je Multiplication
cmp ebp, DIVISION
je Division
Addition:
adc operand_1, operand_2
jmp Output
Subtraction:
sbb operand_1, operand_2
jmp Output
Multiplication:
imul operand_1, operand_2
jmp Output
Division:
cmp operand_2, 00h
je Division_By_Zero
idiv operand_1, operand_2
jmp Output
Output:
;***********************
; Display Output Prompt
;***********************
invoke WriteConsoleA, handle_standard_out, offset output_prompt, \
sizeof output_prompt, offset bytes_written, NULL_POINTER
;****************
; Display Output
;****************
invoke WriteConsoleA, handle_standard_out, offset output_buffer, \
sizeof output_buffer, offset bytes_written, NULL_POINTER
Invalid_Input:
movzx return_code, RETURN_ERROR
Finish:
invoke ExitProcess, return_code
Main endp
ASCII_To_Decimal proc stdcall uses ebx ecx edx esi edi ebp,
local Pre_Start_ASCII_To_Decimal:
xor ebx, ebx
cmp byte ptr esi[ebx], SIGN
je Next_Index_ASCII_To_Decimal
cmp byte ptr esi[ebx], 00h
jb Invalid_Input
cmp byte ptr esi[ebx], 09h
ja Invalid_Input
movzx edx, byte ptr esi[ebx]
sub edx, ZERO_CHAR
add eax, edx
add ebx, 01h
local Start_ASCII_To_Decimal:
cmp ecx, 00h
je Is_Sign_ASCII_To_Decimal
movzx edx, eax
shl eax, 03h
add eax, edx
add eax, edx
movzx edx, byte ptr esi[ebx]
sub edx, ZERO_CHAR
add eax, edx
add ebx, 01h
sub ecx, 01h
jmp Start_ASCII_To_Decimal
local Next_Index_ASCII_To_Decimal:
add ebx, 01h
sub ecx, 01h
jmp Start_ASCII_To_Decimal
local Is_Sign_ASCII_To_Decimal:
cmp byte ptr esi[00h], SIGN
jne Finish_ASCII_To_Decimal
neg eax
local Finish_ASCII_To_Decimal:
ret
ASCII_To_Decimal endp
Decimal_To_ASCII proc stdcall uses eax ebx edx esi edi ebp,
ret
Decimal_To_ASCII endp
end Main
;------------------------------------------------------------------------------
; HEADING
;------------------------------------------------------------------------------
; redacted
;------------------------------------------------------------------------------
; HISTORY
;------------------------------------------------------------------------------
; Version 1.0
;------------------------------------------------------------------------------
; PURPOSE
;------------------------------------------------------------------------------
; The purpose of this program is to emulate/parse a mathematical equation
;------------------------------------------------------------------------------
; MASM BUILD TYPE
;------------------------------------------------------------------------------
.586
;------------------------------------------------------------------------------
; MODEL, STANDARD, and Option TYPES
;------------------------------------------------------------------------------
.MODEL flat, stdcall
option casemap :none ;makes it case sensitive
;------------------------------------------------------------------------------
; LIBRARIES/MODULES
;------------------------------------------------------------------------------
;I had issues with trying to link to the "win32API.asm" file, (pasted it below)
;********************************************************
; Masm Include File for Windows 32-Bit API Functions
;
; The information contained in this file can be found at
; http://msdn.microsoft.com/en-us/library/default.aspx
;
;********************************************************
;********************************************************
; WINDOWS API FUNCTION PROTOTYPES
;********************************************************
ExitProcess PROTO : DWORD
GetStdHandle PROTO : DWORD
ReadConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
SetConsoleCursorPosition PROTO : DWORD, : DWORD
SetConsoleMode PROTO : DWORD, : DWORD
SetConsoleTextAttribute PROTO : DWORD, : DWORD
WriteConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
FlushConsoleInputBuffer PROTO : DWORD
CreateThread PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
CreateMutexA PROTO : DWORD, : DWORD, : DWORD
ReleaseMutex PROTO :DWORD
Sleep PROTO : DWORD
WaitForSingleObject PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD, :DWORD, :DWORD
SuspendThread PROTO : DWORD
ResumeThread PROTO : DWORD
ExitThread PROTO : DWORD
CreateFileA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
ReadFile PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
GetFileSize PROTO : DWORD, : DWORD
CloseHandle PROTO : DWORD
TIMECAPS Struct
wPeriodMin DWORD ?
wPeriodMax DWORD ?
TIMECAPS Ends
timeGetDevCaps PROTO : DWORD, : DWORD
timeBeginPeriod PROTO : DWORD
timeGetTime PROTO
GetTickCount PROTO
QueryPerformanceCounter PROTO : DWORD
QueryPerformanceFrequency PROTO : DWORD
GetLastError PROTO
;********************************************************
; EQUATES
;********************************************************
NULL EQU 0
;*****************************************************
; Standard Handles
;*****************************************************
STD_INPUT_HANDLE EQU -10 ;Standard Input Handle
STD_OUTPUT_HANDLE EQU -11 ;Standard Output Handle
STD_ERROR_HANDLE EQU -12 ;Standard Error Handle
GENERIC_ALL EQU 10000000h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
FILE_SHARE_NONE EQU 0
FILE_SHARE_DELETE EQU 4
FILE_SHARE_READ EQU 1
FILE_SHARE_WRITE EQU 2
CREATE_NEW EQU 1
CREATE_ALWAYS EQU 2
OPEN_EXISTING EQU 3
OPEN_ALWAYS EQU 4
TRUNCATE_EXISTING EQU 5
FILE_ATTRIBUTE_NORMAL EQU 80h
;*****************************************************
; Set Console Mode Equates
;
; Refer to Microsoft's documentation on SetConsoleMode
; for a complete description of these equates.
;*****************************************************
ENABLE_NOTHING_INPUT EQU 0000h ;Turn off all input options
ENABLE_ECHO_INPUT EQU 0004h ;Characters read are written to the active screen buffer (can be used with ENABLE_LINE_INPUT)
ENABLE_INSERT_MODE EQU 0020h ;When enabled, text entered in a console window will be inserted at the current cursor location
ENABLE_LINE_INPUT EQU 0002h ;The ReadConsole function returns only when a carriage return character is read.
ENABLE_MOUSE_INPUT EQU 0010h ;If the mouse is within the borders of the console window & the window has the keyboard focus, mouse events are placed in the input buffer. These events are discarded by ReadFile or ReadConsole.
ENABLE_PROCESSED_INPUT EQU 0001h ;CTRL+C is processed by the system and is not placed in the input buffer.
ENABLE_QUICK_EDIT_MODE EQU 0040h ;This flag enables the user to use the mouse to select and edit text. To enable this option, use the OR to combine this flag with ENABLE_EXTENDED_FLAGS.
ENABLE_WINDOW_INPUT EQU 0008h ;User interactions that change the size of the console screen buffer are reported in the console's input buffer.
;If the hConsoleHandle parameter is a screen buffer handle, the mode can be one or more of the following values. When a screen buffer is created, both output modes are enabled by default.
ENABLE_PROCESSED_OUTPUT EQU 0001h ;Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or ReadConsole function are examined for ASCII control sequences and the correct action is performed.
ENABLE_WRAP_AT_EOL_OUTPUT EQU 0002h ;When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the cursor moves to the beginning of the next row when it reaches the end of the current row.
;********************************************************
; CONSOLE FOREGROUND AND BACKGROUND COLOR EQUATES
;********************************************************
FOREGROUND_BLACK EQU 0
FOREGROUND_DARK_BLUE EQU 1
FOREGROUND_DARK_GREEN EQU 2
FOREGROUND_DARK_CYAN EQU 3
FOREGROUND_DARK_RED EQU 4
FOREGROUND_DARK_MAGENTA EQU 5
FOREGROUND_DARK_YELLOW EQU 6
FOREGROUND_GRAY EQU 7
FOREGROUND_DARK_GRAY EQU 8
FOREGROUND_BLUE EQU 9
FOREGROUND_GREEN EQU 10
FOREGROUND_CYAN EQU 11
FOREGROUND_RED EQU 12
FOREGROUND_MAGENTA EQU 13
FOREGROUND_YELLOW EQU 14
FOREGROUND_WHITE EQU 15
BACKGROUND_BLACK EQU FOREGROUND_BLACK * 10h
BACKGROUND_DARK_BLUE EQU FOREGROUND_DARK_BLUE * 10h
BACKGROUND_DARK_GREEN EQU FOREGROUND_DARK_GREEN * 10h
BACKGROUND_DARK_CYAN EQU FOREGROUND_DARK_CYAN * 10h
BACKGROUND_DARK_RED EQU FOREGROUND_DARK_RED * 10h
BACKGROUND_DARK_MAGENTA EQU FOREGROUND_DARK_MAGENTA * 10h
BACKGROUND_DARK_YELLOW EQU FOREGROUND_DARK_YELLOW * 10h
BACKGROUND_GRAY EQU FOREGROUND_GRAY * 10h
BACKGROUND_DARK_GRAY EQU FOREGROUND_DARK_GRAY * 10h
BACKGROUND_BLUE EQU FOREGROUND_BLUE * 10h
BACKGROUND_GREEN EQU FOREGROUND_GREEN * 10h
BACKGROUND_CYAN EQU FOREGROUND_CYAN * 10h
BACKGROUND_RED EQU FOREGROUND_RED * 10h
BACKGROUND_MAGENTA EQU FOREGROUND_MAGENTA * 10h
BACKGROUND_YELLOW EQU FOREGROUND_YELLOW * 10h
BACKGROUND_WHITE EQU FOREGROUND_WHITE * 10h
;------------------------------------------------------------------------------
; STACK SIZE
;------------------------------------------------------------------------------
.STACK 4096
;------------------------------------------------------------------------------
; RADIX TYPE
;------------------------------------------------------------------------------
; (placeholder)
;------------------------------------------------------------------------------
; DATA SEGMENT (DS)
;------------------------------------------------------------------------------
.DATA
;*********************
; EQUATES/ENUMERATORS
;*********************
CARRIAGE_RETURN EQU 0Dh
NEW_LINE_FEED EQU 0Ah
NULL_POINTER EQU 00h
MAX_INPUT_BUFFER_SIZE EQU 1Bh
MAX_OUTPUT_BUFFER_SIZE EQU 29h
SPACE EQU 20h
EQUAL EQU 3Dh
NEGATIVE EQU 2Dh
ADDITION EQU 2Bh
SUBTRACTION EQU 2Dh
MULTIPLICATION EQU 2Ah
DIVISON EQU 2Ch
ZERO_ASCII EQU 30h
RETURN_ERROR EQU 01h
;***********
; VARIABLES
;***********
heading byte "redacted",
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
history byte "Version 1.0", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
purpose byte "This program's purpose is to evaluate/parse",\
" a mathematical equation", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
input_prompt byte "Enter a mathematical equation in the form of"\
", <value(space)operation(space)value> , : ", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
output_prompt byte CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED,\
"The result is:", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
division_by_zero byte "Error: Division by zero, result is undefined"\
, CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
overflow_flagged byte "Overflow occurred", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
underflow_flagged byte "Underflow occurred", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
input_buffer byte INPUT_BUFFER_SIZE dup (?)
output_buffer byte OUTPUT_BUFFER_SIZE dup (?)
operator_variable byte ?
operand_1 sdword ?
operand_2 sdword ?
result_value sdword ?
return_code dword 00h
bytes_read dword ?
bytes_written dword ?
handle_standard_out dword ?
handle_standard_in dword ?
;------------------------------------------------------------------------------
; CODE SEGMENT (CS)
;------------------------------------------------------------------------------
.CODE
Main Proc
;*******************************
; Get handle to standard output
;*******************************
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov handle_stardard_out, eax
;******************************
; Get handle to standard input
;******************************
invoke GetStdHandle, STD_INPUT_HANDLE
mov handle_standard_in, eax
;**************
; Program Info
;**************
invoke WriteConsoleA, handle_standard_out, offset heading, \
sizeof heading, offset bytes_written, NULL_POINTER
invoke WriteConsoleA, handle_standard_out, offset history, \
sizeof history, offset bytes_written, NULL_POINTER
invoke WriteConsoleA, handle_standard_out, offset purpose, \
sizeof heading, offset bytes_written, NULL_POINTER
;***********************
; Prompt for User Input
;***********************
invoke WriteConsoleA, handle_standard_out, offset input_prompt, \
sizeof input_prompt, offset bytes_written, NULL_POINTER
;****************
; Get User Input
;****************
invoke ReadConsoleA, handle_standard_in, offset input_buffer, \
sizeof input_buffer, offset bytes_read, NULL_POINTER
;*********
; Program
;*********
Pre_Start:
mov esi, offset input_buffer
mov edi, offset output_buffer
movzx edx, OUTPUT_BUFFER_SIZE
xor ebx, ebx
xor ecx, ecx
Start:
xor eax, eax
Get_Operand_Length:
cmp byte ptr esi[ebx], SPACE
je Set_Operand_1_Length
cmp byte ptr esi[ebx], CARRIAGE_RETURN
je Set_Operand_2_Length
add ebx, 01h
jmp Get_Operand_Length
Set_Operand_1_Length:
movzx ecx, ebx
sub ecx, ebp
Operand_1:
call ASCII_To_Decimal (esi, ecx)
movzx operand_1, eax
movzx ebp, ebx
Skip_To_Operator:
add ebx, 02h
Store_Operator:
movzx operator_variable, byte ptr esi[ebx]
Skip_Past_Operator_To_Handling_Operand_2:
add ebx, 02h
jnp Start
Set_Operand_2_Length:
movzx ecx, ebx
sub ecx, ebp
Operand_2:
call ASCII_To_Decimal (esi, ecx)
movzx operand_2, eax
Storing_Actual_Array_Length:
; movzx xxx_variable, ebx
; movzx ecx, ebx
Zeroing_Registers:
; xor eax, eax
; xor ecx, ecx
; xor edx, edx
Determining_Arithmetic_Operation:
movzx ebp, operator_variable
cmp ebp, ADDITION
je Addition
cmp ebp, SUBTRACTION
je Subtraction
cmp ebp, MULTIPLICATION
je Multiplication
cmp ebp, DIVISION
je Division
Addition:
mov eax, dword ptr operand_1 + 4
mov ecx, dword ptr operand_2 + 4
adc eax, ecx
mov dword ptr result_value + 4, eax
jmp Conversion
Subtraction:
mov eax, dword ptr operand_1 + 4
mov ecx, dword ptr operand_2 + 4
sbb eax, ecx
mov dword ptr result_value + 4, eax
jmp Conversion
Multiplication:
mov eax, dword ptr operand_1
mov ecx, dword ptr operand_2
imul ecx
mov dword ptr result_value, eax
jmp Conversion
Division:
mov eax, dword ptr operand_1
mov ecx, dword ptr operand_2
idiv ecx
mov dword ptr result_value, eax
jmp Conversion
Conversion:
call Decimal_To_ASCII
Output:
;***********************
; Display Output Prompt
;***********************
invoke WriteConsoleA, handle_standard_out, offset output_prompt, \
sizeof output_prompt, offset bytes_written, NULL_POINTER
;****************
; Display Output
;****************
invoke WriteConsoleA, handle_standard_out, offset output_buffer, \
sizeof output_buffer, offset bytes_written, NULL_POINTER
jmp Finish
Invalid_Input:
movzx return_code, RETURN_ERROR
Finish:
invoke ExitProcess, return_code
Main endp
ASCII_To_Decimal proc stdcall uses ebx ecx edx esi edi ebp,
local Pre_Start_ASCII_To_Decimal:
xor ebx, ebx
cmp byte ptr esi[ebx], SIGN
je Next_Index_ASCII_To_Decimal
cmp byte ptr esi[ebx], 00h
jb Invalid_Input
cmp byte ptr esi[ebx], 09h
ja Invalid_Input
movzx edx, byte ptr esi[ebx]
sub edx, ZERO_CHAR
add eax, edx
add ebx, 01h
local Start_ASCII_To_Decimal:
cmp ecx, 00h
je Is_Sign_ASCII_To_Decimal
movzx edx, eax
shl eax, 03h
add eax, edx
add eax, edx
movzx edx, byte ptr esi[ebx]
sub edx, ZERO_CHAR
add eax, edx
add ebx, 01h
sub ecx, 01h
jmp Start_ASCII_To_Decimal
local Next_Index_ASCII_To_Decimal:
add ebx, 01h
sub ecx, 01h
jmp Start_ASCII_To_Decimal
local Is_Sign_ASCII_To_Decimal:
cmp byte ptr esi[00h], SIGN
jne Finish_ASCII_To_Decimal
neg eax
local Finish_ASCII_To_Decimal:
ret
ASCII_To_Decimal endp
Decimal_To_ASCII proc stdcall uses eax ebx edx esi edi ebp,
ret
Decimal_To_ASCII endp
end Main
If I understand correctly, the 'uses' key-word/command, merely copies the registers' (original) values into/onto the stack for storage, so that once you're done with the procedure, those original values are loaded/copied/moved back into your registers, over-writing whatever values were currently in them from your procedure operations.
With this understanding, then why would you need to indirectly (via parameters) use registers in/for your procedures ???
Unofrtunately, the required given procedure only mentions/specifies that the array source address (in esi) and its size/length (in ecx) are to be used as its args.
local Pre_Start_ASCII_To_Decimal:
xor ebx, ebx
cmp byte ptr esi[ebx], SIGN
je Next_Index_ASCII_To_Decimal
cmp byte ptr esi[ebx], 00h
jb Invalid_Input
cmp byte ptr esi[ebx], 09h
ja Invalid_Input
movzx edx, byte ptr esi[ebx]
sub edx, ZERO_CHAR
add eax, edx
add ebx, 01h
local Start_ASCII_To_Decimal:
local Pre_Start_ASCII_To_Decimal:
xor ebx, ebx
xor eax, eax
cmp byte ptr esi[ebx], SIGN
jne Start_ASCII_To_Decimal
inc ebx
dec ecx
local Start_ASCII_To_Decimal:
local Pre_Start_ASCII_To_Decimal:
xor ebx, ebx
xor eax, eax
cmp byte ptr esi[ebx], SIGN
jne Start_ASCII_To_Decimal
inc ebx
dec ecx
local Start_ASCII_To_Decimal:
cmp byte ptr esi[ebx], 00h
jb Invalid_Input
cmp byte ptr esi[ebx], 09h
ja Invalid_Input
Addition:
mov eax, dword ptr operand_1 + 4
mov ecx, dword ptr operand_2 + 4
adc eax, ecx
mov dword ptr result_value + 4, eax
jmp Conversion
HegemonKhan wrote:ah, thanks for all the help! I have no clue on how to do the arithmetic operations... we got power point slides on the instruction sets, so I was just using them, and saw that the example was a 'word' with '+2', so that's where my '+4' came from, as I'm like okay maybe I do +4 for dwords lol, as I think I'm using dwords as the regs are dwords/32 bits, or should I use a different data type?
HegemonKhan wrote:alright, so I don't need to use the adc/sbb, right? I just used them as I thought I'd need them to deal with the flags (carry/sign/zero/etc) ... I really have no clue on any of this arithmetic stuff, I've never done it before, and don't understand it at all.
how do I handle the arithmetic, and possibly flag usages too ???
HegemonKhan wrote:I found an online edu resource that gets a bit into explaining the multiplication for me:
algorithms: repeated addition, 'shift and' add, parallel multiplication,
negative numbers:
convert to positive, multiply, then convert back to negative if only one was negative,
etc etc etc
------------
how much do the instruction sets handle, vs what you have to do/account for ???
ESP +0 +4 +8 +12
Return address | Argument 1 (input buf) | Argument 2 (input length) | Argument 3 (output buf)
ESP +0 +4 +8 +12 +16
saved ebp | Return address | Argument 1 (input buf) | Argument 2 (input length) | Argument 3 (output buf)
Jaynabonne wrote:The prototype you have looks wrong to me. I think it should be this:
DWORD RLE_Encode (char *InputBuf, DWORD InputLength, char *OutputBuf);
It takes a char* input buffer and the length of that input buffer, it writes the encoded data into OutputBuf (which is also a pointer), and then it returns the length of the encoded data, so you know how big the encoded data ended up being.
It is correct to use BYTE for the data type; you'll be reading and writing bytes. (Technically, the signature for the C function should probably be "unsigned char*" instead of just "char*", but that won't make any difference to your assembly code.)
.model flat, c ; specify C calling convention
RlEncode PROC sourceBuffer:LPVOID, sourceSize:DWORD, outputBuffer:LPVOID
mov esi, sourceBuffer
mov ecx, sourceSize
mov edi, outputBuffer
; do stuff with them
ret
RlEncode endp
JayNabonne wrote:The run length encoding has two forms: if the two high bits of the byte are set, then the bottom six are the length, and the next byte after the count byte is the data byte to use. If the two top bits aren't both set, then the byte is just the data byte. So if you had this *encoded*:
C8 (11001000)
FF
the decoder would decode 8 0FFh bytes.
CF (11001111)
00
the decoder would decode 15 (00fh) 00 bytes
AA (10101010)
the decoder would decode a single 0AAh byte.
00 (00000000)
the decoder would decode a single 000h byte.
FF (11111111)
CC
the decoder would decode 63 (111111b = 03fh) 0cch bytes
where does your '1,2,3,4,9,10' come from, or are those just example values?
ya, you understood about my 'X/XX/NA' correctly! I wasn't sure if the next value (AA) went into its lsb, or if I were to place a '00' into its hsb and the 'AA' would be in the next unit (byte)
example pseudocode:
start:
store (new/next) value
cmp stored_value' bits (7+6), 11h ; to determine which operation I do
cmps buffer_data, stored_value ; checking for when the value changes (end of current data value's count)
loop start
is this correct ???
outer:
read next byte
inc position in buffer
dec source bytes left - if 0, jump to finish.
set count to 1
inner:
compare next value in buffer (buffer + offset + 1)to current value
if not equal jump to write
inc position in buffer
inc count
dec source bytes left - if 0, jump to finish.
jmp inner
write:
write the count + data to buffer as detailed above
jmp outer
finish:
write the count + data to buffer as detailed above <- could be your own subroutine since you need it in two places.
load up eax with the final count
return
;------------------------------------------------------------------------------
; HEADING
;------------------------------------------------------------------------------
; redacted
; Due: 5:00 pm, Wed., April. 6, 2016
;------------------------------------------------------------------------------
; HISTORY
;------------------------------------------------------------------------------
; Version 1.0
;------------------------------------------------------------------------------
; Credit (those who helped me)
;------------------------------------------------------------------------------
; Online person Jay
; (various online webpage resources, that I need to add in here still)
; (a few colleagues' help too)
;------------------------------------------------------------------------------
; PURPOSE
;------------------------------------------------------------------------------
; The purpose of this program is to encode (compress) a data file.
;------------------------------------------------------------------------------
; MASM BUILD TYPE
;------------------------------------------------------------------------------
.586
;------------------------------------------------------------------------------
; MODEL, STANDARD, and Option TYPES
;------------------------------------------------------------------------------
.MODEL flat, stdcall
option casemap :none ;makes it case sensitive
PUBLIC RLE_Encode
;------------------------------------------------------------------------------
; LIBRARIES/MODULES
;------------------------------------------------------------------------------
;I had issues with trying to link to the "win32API.asm" file, (pasted it below)
;********************************************************
; Masm Include File for Windows 32-Bit API Functions
;
; The information contained in this file can be found at
; http://msdn.microsoft.com/en-us/library/default.aspx
;
;********************************************************
;********************************************************
; WINDOWS API FUNCTION PROTOTYPES
;********************************************************
ExitProcess PROTO : DWORD
GetStdHandle PROTO : DWORD
ReadConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
SetConsoleCursorPosition PROTO : DWORD, : DWORD
SetConsoleMode PROTO : DWORD, : DWORD
SetConsoleTextAttribute PROTO : DWORD, : DWORD
WriteConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
FlushConsoleInputBuffer PROTO : DWORD
CreateThread PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
CreateMutexA PROTO : DWORD, : DWORD, : DWORD
ReleaseMutex PROTO :DWORD
Sleep PROTO : DWORD
WaitForSingleObject PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD, :DWORD, :DWORD
SuspendThread PROTO : DWORD
ResumeThread PROTO : DWORD
ExitThread PROTO : DWORD
CreateFileA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
ReadFile PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
GetFileSize PROTO : DWORD, : DWORD
CloseHandle PROTO : DWORD
TIMECAPS Struct
wPeriodMin DWORD ?
wPeriodMax DWORD ?
TIMECAPS Ends
timeGetDevCaps PROTO : DWORD, : DWORD
timeBeginPeriod PROTO : DWORD
timeGetTime PROTO
GetTickCount PROTO
QueryPerformanceCounter PROTO : DWORD
QueryPerformanceFrequency PROTO : DWORD
GetLastError PROTO
;********************************************************
; EQUATES
;********************************************************
NULL EQU 0
;*****************************************************
; Standard Handles
;*****************************************************
STD_INPUT_HANDLE EQU -10 ;Standard Input Handle
STD_OUTPUT_HANDLE EQU -11 ;Standard Output Handle
STD_ERROR_HANDLE EQU -12 ;Standard Error Handle
GENERIC_ALL EQU 10000000h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
FILE_SHARE_NONE EQU 0
FILE_SHARE_DELETE EQU 4
FILE_SHARE_READ EQU 1
FILE_SHARE_WRITE EQU 2
CREATE_NEW EQU 1
CREATE_ALWAYS EQU 2
OPEN_EXISTING EQU 3
OPEN_ALWAYS EQU 4
TRUNCATE_EXISTING EQU 5
FILE_ATTRIBUTE_NORMAL EQU 80h
;*****************************************************
; Set Console Mode Equates
;
; Refer to Microsoft's documentation on SetConsoleMode
; for a complete description of these equates.
;*****************************************************
ENABLE_NOTHING_INPUT EQU 0000h ;Turn off all input options
ENABLE_ECHO_INPUT EQU 0004h ;Characters read are written to the active screen buffer (can be used with ENABLE_LINE_INPUT)
ENABLE_INSERT_MODE EQU 0020h ;When enabled, text entered in a console window will be inserted at the current cursor location
ENABLE_LINE_INPUT EQU 0002h ;The ReadConsole function returns only when a carriage return character is read.
ENABLE_MOUSE_INPUT EQU 0010h ;If the mouse is within the borders of the console window & the window has the keyboard focus, mouse events are placed in the input buffer. These events are discarded by ReadFile or ReadConsole.
ENABLE_PROCESSED_INPUT EQU 0001h ;CTRL+C is processed by the system and is not placed in the input buffer.
ENABLE_QUICK_EDIT_MODE EQU 0040h ;This flag enables the user to use the mouse to select and edit text. To enable this option, use the OR to combine this flag with ENABLE_EXTENDED_FLAGS.
ENABLE_WINDOW_INPUT EQU 0008h ;User interactions that change the size of the console screen buffer are reported in the console's input buffer.
;If the hConsoleHandle parameter is a screen buffer handle, the mode can be one or more of the following values. When a screen buffer is created, both output modes are enabled by default.
ENABLE_PROCESSED_OUTPUT EQU 0001h ;Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or ReadConsole function are examined for ASCII control sequences and the correct action is performed.
ENABLE_WRAP_AT_EOL_OUTPUT EQU 0002h ;When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the cursor moves to the beginning of the next row when it reaches the end of the current row.
;********************************************************
; CONSOLE FOREGROUND AND BACKGROUND COLOR EQUATES
;********************************************************
FOREGROUND_BLACK EQU 0
FOREGROUND_DARK_BLUE EQU 1
FOREGROUND_DARK_GREEN EQU 2
FOREGROUND_DARK_CYAN EQU 3
FOREGROUND_DARK_RED EQU 4
FOREGROUND_DARK_MAGENTA EQU 5
FOREGROUND_DARK_YELLOW EQU 6
FOREGROUND_GRAY EQU 7
FOREGROUND_DARK_GRAY EQU 8
FOREGROUND_BLUE EQU 9
FOREGROUND_GREEN EQU 10
FOREGROUND_CYAN EQU 11
FOREGROUND_RED EQU 12
FOREGROUND_MAGENTA EQU 13
FOREGROUND_YELLOW EQU 14
FOREGROUND_WHITE EQU 15
BACKGROUND_BLACK EQU FOREGROUND_BLACK * 10h
BACKGROUND_DARK_BLUE EQU FOREGROUND_DARK_BLUE * 10h
BACKGROUND_DARK_GREEN EQU FOREGROUND_DARK_GREEN * 10h
BACKGROUND_DARK_CYAN EQU FOREGROUND_DARK_CYAN * 10h
BACKGROUND_DARK_RED EQU FOREGROUND_DARK_RED * 10h
BACKGROUND_DARK_MAGENTA EQU FOREGROUND_DARK_MAGENTA * 10h
BACKGROUND_DARK_YELLOW EQU FOREGROUND_DARK_YELLOW * 10h
BACKGROUND_GRAY EQU FOREGROUND_GRAY * 10h
BACKGROUND_DARK_GRAY EQU FOREGROUND_DARK_GRAY * 10h
BACKGROUND_BLUE EQU FOREGROUND_BLUE * 10h
BACKGROUND_GREEN EQU FOREGROUND_GREEN * 10h
BACKGROUND_CYAN EQU FOREGROUND_CYAN * 10h
BACKGROUND_RED EQU FOREGROUND_RED * 10h
BACKGROUND_MAGENTA EQU FOREGROUND_MAGENTA * 10h
BACKGROUND_YELLOW EQU FOREGROUND_YELLOW * 10h
BACKGROUND_WHITE EQU FOREGROUND_WHITE * 10h
;------------------------------------------------------------------------------
; Prototypes
;------------------------------------------------------------------------------
DWORD RLE_Encode (char *InputBuf, DWORD InputLength, char *OutputBuf) public
;------------------------------------------------------------------------------
; STACK SIZE
;------------------------------------------------------------------------------
.STACK 4096
;------------------------------------------------------------------------------
; RADIX TYPE
;------------------------------------------------------------------------------
; (placeholder)
;------------------------------------------------------------------------------
; DATA SEGMENT (DS)
;------------------------------------------------------------------------------
.DATA
;*********************
; EQUATES/ENUMERATORS
;*********************
CARRIAGE_RETURN EQU 0Dh
NEW_LINE_FEED EQU 0Ah
NULL_POINTER EQU 00h
;***********
; VARIABLES
;***********
heading byte "Due: 5:00 pm, Wed., April. 6, 2016",
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
history byte "Version 1.0", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
credit byte "Credits (those who helped me): ", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED, \
"Online person Jay", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
purpose byte "This program's purpose is to encode ", \
"(compress) a data file." \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
;------------------------------------------------------------------------------
; CODE SEGMENT (CS)
;------------------------------------------------------------------------------
.CODE
Main Proc
push eax
call RLE_Encode
;**********************
; Terminating Program
;**********************
Finish:
invoke ExitProcess, NULL_POINTER
Main endp
;************
; Procedures
;************
DWORD RLE_Encode (char *InputBuf, DWORD InputLength, char *OutputBuf) proc public \
stdcall uses ebx, ecx, edx, esi, edi, ebp, esp
push eax
; push ebp
; movzx ebp, esp
; I ran out of registers, not sure what to do, if I can't directly use esp if I need to, if I need to use ebp (storing esp)
; I'm using ebx for tallying-storing the each-time-counts
; I'm using ebp for tallying-getting the length of edi, would 'lengthof edi' work for this instead, or no?
; I'm using eax for storing the each-time-initial value
; I'm using ecx for subtracting the length of the buffer ("EoVs: End of Values -- in the input buffer")
; I'm using edx for storing the the next value, to compare more efficiently (reg:reg) with eax (storing the each-time-initial value)
; I could do reg:mem for the comparison (not using/freeing up the edx), I think I can design-wise anyways, but this would be less efficient than doing reg:reg
movzx esi, InputBuf
movzx ecx, InputLength
movzx edi, OutputBuf
xor edx, edx
Outer_Loop:
movzx eax, byte ptr [esp][esi]
movzx ebx, 01h
sub ecx, 01h
cmp ecx, 00h
je Single_Byte_One
add esi, 01h
Inner_Loop:
movzx edx, byte ptr [esp][esi]
cmp eax, edx
jne Single_Byte_One
add esi, 01h
add ebx, 01h
sub ecx, 01h
cmp ebx, 3Fh
je Multiple_Byte
cmp ecx, 00h
je Multiple_Byte
jmp Inner_Loop
Multiple_Byte:
add ebx, 0C0h
movzx [esp][edi], byte ptr ebx
add edi, 01h
movzx [esp][edi], byte ptr eax
add edi, 01h
add ebp, 02h
cmp ecx, 00h
je Finish
jmp Outer_Loop
Single_Byte_Two:
movzx [esp][edi], byte ptr 0C1h
add edi, 01h
movzx [esp][edi], byte ptr eax
add edi, 01h
add ebp, 02h
cmp ecx, 00h
je Finish
jmp Outer_Loop
Single_Byte_One:
cmp ebx, 01h
jne Multiple_Byte
cmp ah, 0Ch
jae Single_Byte_Two
movzx [esp][edi], byte ptr eax
add edi, 01h
add ebp, 01h
cmp ecx, 00h
jne Outer_Loop
Finish
movzx eax, ebp
pop ebp
pop eax
ret
RLE_Encode endp
;*************************
; Program End/Termination
;*************************
end Main
movzx edx, byte ptr [esp][esi]
cmp eax, edx
jne Single_Byte_One
mov eax, edi
sub eax, OutputBuf
;------------------------------------------------------------------------------
; HEADING
;------------------------------------------------------------------------------
; redacted
; Due: 5:00 pm, Wed., April. 6, 2016
;------------------------------------------------------------------------------
; HISTORY
;------------------------------------------------------------------------------
; Version 1.0
;------------------------------------------------------------------------------
; Credit (those who helped me)
;------------------------------------------------------------------------------
; Online person Jay
; online resources
; colleagues
;------------------------------------------------------------------------------
; PURPOSE
;------------------------------------------------------------------------------
; The purpose of this program is to encode (compress) a data file.
;------------------------------------------------------------------------------
; MASM BUILD TYPE
;------------------------------------------------------------------------------
.586
;------------------------------------------------------------------------------
; MODEL, STANDARD, and Option TYPES
;------------------------------------------------------------------------------
.MODEL flat, stdcall
option casemap :none ;makes it case sensitive
PUBLIC RLE_Encode
;------------------------------------------------------------------------------
; LIBRARIES/MODULES
;------------------------------------------------------------------------------
;I had issues with trying to link to the "win32API.asm" file, (pasted it below)
;********************************************************
; Masm Include File for Windows 32-Bit API Functions
;
; The information contained in this file can be found at
; http://msdn.microsoft.com/en-us/library/default.aspx
;
;********************************************************
;********************************************************
; WINDOWS API FUNCTION PROTOTYPES
;********************************************************
ExitProcess PROTO : DWORD
GetStdHandle PROTO : DWORD
ReadConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
SetConsoleCursorPosition PROTO : DWORD, : DWORD
SetConsoleMode PROTO : DWORD, : DWORD
SetConsoleTextAttribute PROTO : DWORD, : DWORD
WriteConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
FlushConsoleInputBuffer PROTO : DWORD
CreateThread PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
CreateMutexA PROTO : DWORD, : DWORD, : DWORD
ReleaseMutex PROTO :DWORD
Sleep PROTO : DWORD
WaitForSingleObject PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD, :DWORD, :DWORD
SuspendThread PROTO : DWORD
ResumeThread PROTO : DWORD
ExitThread PROTO : DWORD
CreateFileA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
ReadFile PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
GetFileSize PROTO : DWORD, : DWORD
CloseHandle PROTO : DWORD
TIMECAPS Struct
wPeriodMin DWORD ?
wPeriodMax DWORD ?
TIMECAPS Ends
timeGetDevCaps PROTO : DWORD, : DWORD
timeBeginPeriod PROTO : DWORD
timeGetTime PROTO
GetTickCount PROTO
QueryPerformanceCounter PROTO : DWORD
QueryPerformanceFrequency PROTO : DWORD
GetLastError PROTO
;********************************************************
; EQUATES
;********************************************************
NULL EQU 0
;*****************************************************
; Standard Handles
;*****************************************************
STD_INPUT_HANDLE EQU -10 ;Standard Input Handle
STD_OUTPUT_HANDLE EQU -11 ;Standard Output Handle
STD_ERROR_HANDLE EQU -12 ;Standard Error Handle
GENERIC_ALL EQU 10000000h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
FILE_SHARE_NONE EQU 0
FILE_SHARE_DELETE EQU 4
FILE_SHARE_READ EQU 1
FILE_SHARE_WRITE EQU 2
CREATE_NEW EQU 1
CREATE_ALWAYS EQU 2
OPEN_EXISTING EQU 3
OPEN_ALWAYS EQU 4
TRUNCATE_EXISTING EQU 5
FILE_ATTRIBUTE_NORMAL EQU 80h
;*****************************************************
; Set Console Mode Equates
;
; Refer to Microsoft's documentation on SetConsoleMode
; for a complete description of these equates.
;*****************************************************
ENABLE_NOTHING_INPUT EQU 0000h ;Turn off all input options
ENABLE_ECHO_INPUT EQU 0004h ;Characters read are written to the active screen buffer (can be used with ENABLE_LINE_INPUT)
ENABLE_INSERT_MODE EQU 0020h ;When enabled, text entered in a console window will be inserted at the current cursor location
ENABLE_LINE_INPUT EQU 0002h ;The ReadConsole function returns only when a carriage return character is read.
ENABLE_MOUSE_INPUT EQU 0010h ;If the mouse is within the borders of the console window & the window has the keyboard focus, mouse events are placed in the input buffer. These events are discarded by ReadFile or ReadConsole.
ENABLE_PROCESSED_INPUT EQU 0001h ;CTRL+C is processed by the system and is not placed in the input buffer.
ENABLE_QUICK_EDIT_MODE EQU 0040h ;This flag enables the user to use the mouse to select and edit text. To enable this option, use the OR to combine this flag with ENABLE_EXTENDED_FLAGS.
ENABLE_WINDOW_INPUT EQU 0008h ;User interactions that change the size of the console screen buffer are reported in the console's input buffer.
;If the hConsoleHandle parameter is a screen buffer handle, the mode can be one or more of the following values. When a screen buffer is created, both output modes are enabled by default.
ENABLE_PROCESSED_OUTPUT EQU 0001h ;Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or ReadConsole function are examined for ASCII control sequences and the correct action is performed.
ENABLE_WRAP_AT_EOL_OUTPUT EQU 0002h ;When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the cursor moves to the beginning of the next row when it reaches the end of the current row.
;********************************************************
; CONSOLE FOREGROUND AND BACKGROUND COLOR EQUATES
;********************************************************
FOREGROUND_BLACK EQU 0
FOREGROUND_DARK_BLUE EQU 1
FOREGROUND_DARK_GREEN EQU 2
FOREGROUND_DARK_CYAN EQU 3
FOREGROUND_DARK_RED EQU 4
FOREGROUND_DARK_MAGENTA EQU 5
FOREGROUND_DARK_YELLOW EQU 6
FOREGROUND_GRAY EQU 7
FOREGROUND_DARK_GRAY EQU 8
FOREGROUND_BLUE EQU 9
FOREGROUND_GREEN EQU 10
FOREGROUND_CYAN EQU 11
FOREGROUND_RED EQU 12
FOREGROUND_MAGENTA EQU 13
FOREGROUND_YELLOW EQU 14
FOREGROUND_WHITE EQU 15
BACKGROUND_BLACK EQU FOREGROUND_BLACK * 10h
BACKGROUND_DARK_BLUE EQU FOREGROUND_DARK_BLUE * 10h
BACKGROUND_DARK_GREEN EQU FOREGROUND_DARK_GREEN * 10h
BACKGROUND_DARK_CYAN EQU FOREGROUND_DARK_CYAN * 10h
BACKGROUND_DARK_RED EQU FOREGROUND_DARK_RED * 10h
BACKGROUND_DARK_MAGENTA EQU FOREGROUND_DARK_MAGENTA * 10h
BACKGROUND_DARK_YELLOW EQU FOREGROUND_DARK_YELLOW * 10h
BACKGROUND_GRAY EQU FOREGROUND_GRAY * 10h
BACKGROUND_DARK_GRAY EQU FOREGROUND_DARK_GRAY * 10h
BACKGROUND_BLUE EQU FOREGROUND_BLUE * 10h
BACKGROUND_GREEN EQU FOREGROUND_GREEN * 10h
BACKGROUND_CYAN EQU FOREGROUND_CYAN * 10h
BACKGROUND_RED EQU FOREGROUND_RED * 10h
BACKGROUND_MAGENTA EQU FOREGROUND_MAGENTA * 10h
BACKGROUND_YELLOW EQU FOREGROUND_YELLOW * 10h
BACKGROUND_WHITE EQU FOREGROUND_WHITE * 10h
;------------------------------------------------------------------------------
; Prototypes
;------------------------------------------------------------------------------
DWORD RLE_Encode (char *InputBuf, DWORD InputLength, char *OutputBuf) public
;------------------------------------------------------------------------------
; STACK SIZE
;------------------------------------------------------------------------------
.STACK 4096
;------------------------------------------------------------------------------
; RADIX TYPE
;------------------------------------------------------------------------------
; (placeholder)
;------------------------------------------------------------------------------
; DATA SEGMENT (DS)
;------------------------------------------------------------------------------
.DATA
;*********************
; EQUATES/ENUMERATORS
;*********************
CARRIAGE_RETURN EQU 0Dh
NEW_LINE_FEED EQU 0Ah
NULL_POINTER EQU 00h
;***********
; VARIABLES
;***********
heading byte "Due: 5:00 pm, Wed., April. 6, 2016",
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
history byte "Version 1.0", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
credit byte "Credits (those who helped me): ", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED, \
"Online person Jay", \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
purpose byte "This program's purpose is to encode ", \
"(compress) a data file." \
CARRIAGE_RETURN, NEW_LINE_FEED, NEW_LINE_FEED
;------------------------------------------------------------------------------
; CODE SEGMENT (CS)
;------------------------------------------------------------------------------
.CODE
Main Proc
push eax
call RLE_Encode
;**********************
; Terminating Program
;**********************
Finish:
invoke ExitProcess, NULL_POINTER
Main endp
;************
; Procedures
;************
DWORD RLE_Encode (char *InputBuf, DWORD InputLength, char *OutputBuf) proc public \
stdcall uses ebx, ecx, edx, esi, edi, ebp, esp
push ebp
movzx ebp, esp
push eax
movzx esi, InputBuf
movzx ecx, InputLength
movzx edi, OutputBuf
xor edx, edx
Outer_Loop:
movzx eax, byte ptr esi
movzx ebx, 01h
add [esi], 01h
sub ecx, 01h
cmp ecx, 00h
je Single_Byte_One
Inner_Loop:
movzx edx, byte ptr esi
cmp eax, edx
jne Single_Byte_One
add [esi], 01h
add ebx, 01h
sub ecx, 01h
cmp ebx, 3Fh
je Multiple_Byte
cmp ecx, 00h
je Multiple_Byte
jmp Inner_Loop
Multiple_Byte:
add ebx, 0C0h
movzx edi, byte ptr ebx
add [edi], 01h
movzx edi, byte ptr eax
add [edi], 01h
cmp ecx, 00h
je Finish
jmp Outer_Loop
Single_Byte_Two:
movzx edi, byte ptr 0C1h
add [edi], 01h
movzx edi, byte ptr eax
add [edi], 01h
cmp ecx, 00h
je Finish
jmp Outer_Loop
Single_Byte_One:
cmp ebx, 01h
jne Multiple_Byte
cmp ah, 0Ch
jae Single_Byte_Two
movzx edi, byte ptr eax
add [edi], 01h
cmp ecx, 00h
jne Outer_Loop
Finish
mov eax, [edi]
sub eax, [OutputBuf]
pop eax
pop ebp
ret
RLE_Encode endp
;*************************
; Program End/Termination
;*************************
end Main
I use 'add' as I thought it was slightly more efficient than 'inc'
do I need to use 'adc' instead, how do I handle the overflow from the low nibble (count value) into the upper nibble ??
(for now, I'm just leaving it as the movzx 32-bit regs and byte ptr stuff usage, I'll go back later and see if I can convert it successfully over to using the 16 and 8 bit sub-division regs, and whether I need the 'byte ptrs' or not, later)
.586
.MODEL flat, stdcall
option casemap :none
public _RLE_Encode ; Do I need this?
dword _RLE_Encode (char *InputBuf, dword InputLength, char *OutputBuf) public ; Is this correct? I keep this like this, or no?
.STACK 4096
.DATA
;blah stuff
.CODE
; main proc
; what do I do here, do I even need this stuff, do I just have the encode procedure ???
; push eax ; do I need this here? do I want to push eax or not, as it's suppose to be used by the C++ to return the OutputBuf length, I think
; call _RLE_Encode ; or am I too use 'invoke' instead?
; Finish:
; invoke ExitProcess, 00h
; Main endp
_RLE_Encode proc public ; is this correct header?
; is this stuff below correct? especially whether I use the 32 bit regs, 16 bit regs, or the 8 bit regs, whether I need to use data type pointers, whether I bracket a reg or not, and etc... I'm just so confused now, I don't know what's right and what's wrong, I'm just not understanding this stuff that well.
push ebp
mov ebp, esp
; do I need to add/sub from esp/ebp ???
; push the other regs ; does this go here?
; push eax ; do I need this here? do I want to push eax or not, as it's suppose to be used by the C++ to return the OutputBuf length, I think
; push the other regs ; does this go here?
; what do I push for the 'return address' byte slot: [ebp+4] ???
mov esi, [ebp+8] ; will it be more than '+8' if I push the other regs?
mov ecx, [ebp+12] ; will it be more than '+12' if I push the other regs?
mov edi, [ebp+16] ; will it be more than '+16' if I push the other regs?
Outer_Loop:
mov al, esi
mov bl, 01h
inc [esi]
dec ecx
cmp cl, 00h
je Single_Byte_One
Inner_Loop:
mov dl, esi
cmp al, dl
jne Single_Byte_One
inc [esi]
inc ebx
dec ecx
cmp bl, 3Fh
je Multiple_Byte
cmp cl, 00h
je Multiple_Byte
jmp Inner_Loop
Multiple_Byte:
or bl, 0C0h
mov edi, bl
inc [edi]
mov edi, al
inc [edi]
cmp cl, 00h
je Finish
jmp Outer_Loop
Single_Byte_Two:
mov edi, 0C1h
inc [edi]
mov edi, al
inc [edi]
cmp cl, 00h
je Finish
jmp Outer_Loop
Single_Byte_One:
cmp bl, 01h
jne Multiple_Byte
cmp ah, 0Ch
jae Single_Byte_Two
mov edi, al
inc [edi]
cmp cl, 00h
jne Outer_Loop
Finish:
mov al, [edi]
sub al, [OutputBuf]
; do I need to add/sub from esp/ebp ???
; pop other regs ; does this go here ?
; pop eax ; does this even get pushed/popper or not?
; pop other regs ; does this go here ?
; pop ebp
; ret ; do I need to add/sub a value here ???
_RLE_Encode endp
; end Main
.586
.MODEL flat, stdcall
option casemap :none
public _RLE_Encode ; Do I need this?
dword _RLE_Encode (char *InputBuf, dword InputLength, char *OutputBuf) public ; Is this correct? I keep this like this, or no?
---- I don't think you need this. I could be wrong, but you don't need to tell the compiler params, since you're doing it yourself.
---- Having said that, when I did assembly language, we didn't have that feature. I could look at it more, if you wish.
.STACK 4096
.DATA
;blah stuff
.CODE
; main proc
; what do I do here, do I even need this stuff, do I just have the encode procedure ???
; push eax ; do I need this here? do I want to push eax or not, as it's suppose to be used by the C++ to return the OutputBuf length, I think
; call _RLE_Encode ; or am I too use 'invoke' instead?
; Finish:
; invoke ExitProcess, 00h
---- You shouldn't need that. You're not calling your function from here. The "main" entry point will be supplied by the C code,
---- which will be calling this as a subroutine.
; Main endp
_RLE_Encode proc public ; is this correct header?
---- I think that looks ok.
; is this stuff below correct? especially whether I use the 32 bit regs, 16 bit regs, or the 8 bit regs, whether I need to use data type pointers, whether I bracket a reg or not, and etc... I'm just so confused now, I don't know what's right and what's wrong, I'm just not understanding this stuff that well.
push ebp
mov ebp, esp
; do I need to add/sub from esp/ebp ???
---- You would only need to sub further from esp if you were using local (temporary/auto) variables on the stack.
---- You shouldn't need to (you should be able to get away with using registers alone), so you can skip that part.
; push the other regs ; does this go here?
---- pushing other registers would go here.
; push eax ; do I need this here? do I want to push eax or not, as it's suppose to be used by the C++ to return the OutputBuf length, I think
---- you will be returning the size in eax, so there's no point in saving it. (It will be lost regardless.)
; push the other regs ; does this go here?
---- Yes, save any other registers here. Not ebp, of course, since it's already saved. :)
; what do I push for the 'return address' byte slot: [ebp+4] ???
---- The return address is already on the stack, pushed there when the C code made the call. That's what allows your ret to go home when done.
mov esi, [ebp+8] ; will it be more than '+8' if I push the other regs?
mov ecx, [ebp+12] ; will it be more than '+12' if I push the other regs?
mov edi, [ebp+16] ; will it be more than '+16' if I push the other regs?
---- You have set ebp to be esp *before* you pushed the registers, and the stack grows downward. So the +8, etc will be the values before your push.
---- So no pushing afterwards will have any effect on the offsets you use.
---- If for some reason you had set ebp *after* you pushed all the registers (not common or recommended), then you would need to change the offsets
---- to account for that, since esp would have changed drastically - which is probably why people don't do it.
Outer_Loop:
mov al, esi ---- mov al, [esi] ; read what esi points to
mov bl, 01h
inc [esi] ---- inc esi ; inc the esi pointer value (not its contents)
dec ecx
cmp cl, 00h ---- this is a 32-bit count, so it would be ecx. However, dec sets the z flag when ecx reaches 0, so you don't even need this line.
je Single_Byte_One
Inner_Loop:
mov dl, esi ---- mov dl,[esi]
cmp al, dl
jne Single_Byte_One
inc [esi] ---- inc esi
inc ebx
dec ecx
cmp bl, 3Fh
je Multiple_Byte
cmp cl, 00h ---- using full 32-bits for count, so this would be ecx.
je Multiple_Byte
jmp Inner_Loop
Multiple_Byte:
or bl, 0C0h
mov edi, bl ---- mov [edi], bl
inc [edi] ---- inc edi
mov edi, al ---- ov [edi], al
inc [edi] ---- inc edi
cmp cl, 00h ---- cmp ecx, 0
je Finish
jmp Outer_Loop
Single_Byte_Two:
mov edi, 0C1h ---- mov byte ptr [edi], 0c1h
inc [edi] ---- inc edi
mov edi, al ---- mov [edi], al
inc [edi] ---- inc edi
cmp cl, 00h ---- cmp ecx, 0
je Finish
jmp Outer_Loop
Single_Byte_One:
cmp bl, 01h
jne Multiple_Byte
cmp ah, 0Ch ---- cmp al, 0c0h (nibble confusion? If ah = 12h and al = 34h, then ax would be 1234h. So c0h is just in al. It doesn't touch ah)
jae Single_Byte_Two
mov edi, al ---- mov [edi],al
inc [edi] ---- inc edi
cmp cl, 00h ---- cmp ecx,0
jne Outer_Loop
Finish:
mov al, [edi] ---- mov eax, edi ; count is full 32-bit value. You only would use the byte registers for the data bytes, not the counts.
sub al, [OutputBuf] ---- sub eax, [ebp+16]
; do I need to add/sub from esp/ebp ???
---- no adjustment needed, since you have no locals
; pop other regs ; does this go here ?
---- yes, pop the registers you pushed here (but not ebp yet)
; pop eax ; does this even get pushed/popper or not?
---- if you pushed and popped eax, you'd lose your return value. So, no.
; pop ebp
; ret ; do I need to add/sub a value here ???
---- if this is C calling convention, then you would just use "ret", as the caller will pop the arguments
---- If it's stdcall, then you need to clean the stack, so it would be "ret 12" to remove the pushed arguments.
_RLE_Encode endp
; end Main
;------------------------------------------------------------------------------
; HEADING
;------------------------------------------------------------------------------
; redacted
; Due: 5:00 pm, Wed., April. 6, 2016
;------------------------------------------------------------------------------
; HISTORY
;------------------------------------------------------------------------------
; Version 1.0
;------------------------------------------------------------------------------
; Credit (those who helped me)
;------------------------------------------------------------------------------
; Online person Jay
; online resources (need to get/paste them here still)
; Colleagues in/from class
;------------------------------------------------------------------------------
; PURPOSE
;------------------------------------------------------------------------------
; The purpose of this program is to encode (compress) a data file.
;------------------------------------------------------------------------------
; MASM BUILD TYPE
;------------------------------------------------------------------------------
.586
;------------------------------------------------------------------------------
; MODEL, STANDARD, and Option TYPES
;------------------------------------------------------------------------------
.MODEL flat, stdcall
option casemap :none ;makes it case sensitive
;------------------------------------------------------------------------------
; LIBRARIES/MODULES
;------------------------------------------------------------------------------
;I had issues with trying to link to the "win32API.asm" file, (pasted it below)
;********************************************************
; Masm Include File for Windows 32-Bit API Functions
;
; The information contained in this file can be found at
; http://msdn.microsoft.com/en-us/library/default.aspx
;
;********************************************************
;********************************************************
; WINDOWS API FUNCTION PROTOTYPES
;********************************************************
ExitProcess PROTO : DWORD
GetStdHandle PROTO : DWORD
ReadConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
SetConsoleCursorPosition PROTO : DWORD, : DWORD
SetConsoleMode PROTO : DWORD, : DWORD
SetConsoleTextAttribute PROTO : DWORD, : DWORD
WriteConsoleA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
FlushConsoleInputBuffer PROTO : DWORD
CreateThread PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
CreateMutexA PROTO : DWORD, : DWORD, : DWORD
ReleaseMutex PROTO :DWORD
Sleep PROTO : DWORD
WaitForSingleObject PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD, :DWORD, :DWORD
SuspendThread PROTO : DWORD
ResumeThread PROTO : DWORD
ExitThread PROTO : DWORD
CreateFileA PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
ReadFile PROTO : DWORD, : DWORD, : DWORD, : DWORD, : DWORD
GetFileSize PROTO : DWORD, : DWORD
CloseHandle PROTO : DWORD
TIMECAPS Struct
wPeriodMin DWORD ?
wPeriodMax DWORD ?
TIMECAPS Ends
timeGetDevCaps PROTO : DWORD, : DWORD
timeBeginPeriod PROTO : DWORD
timeGetTime PROTO
GetTickCount PROTO
QueryPerformanceCounter PROTO : DWORD
QueryPerformanceFrequency PROTO : DWORD
GetLastError PROTO
;********************************************************
; EQUATES
;********************************************************
NULL EQU 0
;*****************************************************
; Standard Handles
;*****************************************************
STD_INPUT_HANDLE EQU -10 ;Standard Input Handle
STD_OUTPUT_HANDLE EQU -11 ;Standard Output Handle
STD_ERROR_HANDLE EQU -12 ;Standard Error Handle
GENERIC_ALL EQU 10000000h
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
FILE_SHARE_NONE EQU 0
FILE_SHARE_DELETE EQU 4
FILE_SHARE_READ EQU 1
FILE_SHARE_WRITE EQU 2
CREATE_NEW EQU 1
CREATE_ALWAYS EQU 2
OPEN_EXISTING EQU 3
OPEN_ALWAYS EQU 4
TRUNCATE_EXISTING EQU 5
FILE_ATTRIBUTE_NORMAL EQU 80h
;*****************************************************
; Set Console Mode Equates
;
; Refer to Microsoft's documentation on SetConsoleMode
; for a complete description of these equates.
;*****************************************************
ENABLE_NOTHING_INPUT EQU 0000h ;Turn off all input options
ENABLE_ECHO_INPUT EQU 0004h ;Characters read are written to the active screen buffer (can be used with ENABLE_LINE_INPUT)
ENABLE_INSERT_MODE EQU 0020h ;When enabled, text entered in a console window will be inserted at the current cursor location
ENABLE_LINE_INPUT EQU 0002h ;The ReadConsole function returns only when a carriage return character is read.
ENABLE_MOUSE_INPUT EQU 0010h ;If the mouse is within the borders of the console window & the window has the keyboard focus, mouse events are placed in the input buffer. These events are discarded by ReadFile or ReadConsole.
ENABLE_PROCESSED_INPUT EQU 0001h ;CTRL+C is processed by the system and is not placed in the input buffer.
ENABLE_QUICK_EDIT_MODE EQU 0040h ;This flag enables the user to use the mouse to select and edit text. To enable this option, use the OR to combine this flag with ENABLE_EXTENDED_FLAGS.
ENABLE_WINDOW_INPUT EQU 0008h ;User interactions that change the size of the console screen buffer are reported in the console's input buffer.
;If the hConsoleHandle parameter is a screen buffer handle, the mode can be one or more of the following values. When a screen buffer is created, both output modes are enabled by default.
ENABLE_PROCESSED_OUTPUT EQU 0001h ;Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or ReadConsole function are examined for ASCII control sequences and the correct action is performed.
ENABLE_WRAP_AT_EOL_OUTPUT EQU 0002h ;When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the cursor moves to the beginning of the next row when it reaches the end of the current row.
;********************************************************
; CONSOLE FOREGROUND AND BACKGROUND COLOR EQUATES
;********************************************************
FOREGROUND_BLACK EQU 0
FOREGROUND_DARK_BLUE EQU 1
FOREGROUND_DARK_GREEN EQU 2
FOREGROUND_DARK_CYAN EQU 3
FOREGROUND_DARK_RED EQU 4
FOREGROUND_DARK_MAGENTA EQU 5
FOREGROUND_DARK_YELLOW EQU 6
FOREGROUND_GRAY EQU 7
FOREGROUND_DARK_GRAY EQU 8
FOREGROUND_BLUE EQU 9
FOREGROUND_GREEN EQU 10
FOREGROUND_CYAN EQU 11
FOREGROUND_RED EQU 12
FOREGROUND_MAGENTA EQU 13
FOREGROUND_YELLOW EQU 14
FOREGROUND_WHITE EQU 15
BACKGROUND_BLACK EQU FOREGROUND_BLACK * 10h
BACKGROUND_DARK_BLUE EQU FOREGROUND_DARK_BLUE * 10h
BACKGROUND_DARK_GREEN EQU FOREGROUND_DARK_GREEN * 10h
BACKGROUND_DARK_CYAN EQU FOREGROUND_DARK_CYAN * 10h
BACKGROUND_DARK_RED EQU FOREGROUND_DARK_RED * 10h
BACKGROUND_DARK_MAGENTA EQU FOREGROUND_DARK_MAGENTA * 10h
BACKGROUND_DARK_YELLOW EQU FOREGROUND_DARK_YELLOW * 10h
BACKGROUND_GRAY EQU FOREGROUND_GRAY * 10h
BACKGROUND_DARK_GRAY EQU FOREGROUND_DARK_GRAY * 10h
BACKGROUND_BLUE EQU FOREGROUND_BLUE * 10h
BACKGROUND_GREEN EQU FOREGROUND_GREEN * 10h
BACKGROUND_CYAN EQU FOREGROUND_CYAN * 10h
BACKGROUND_RED EQU FOREGROUND_RED * 10h
BACKGROUND_MAGENTA EQU FOREGROUND_MAGENTA * 10h
BACKGROUND_YELLOW EQU FOREGROUND_YELLOW * 10h
BACKGROUND_WHITE EQU FOREGROUND_WHITE * 10h
;------------------------------------------------------------------------------
; Prototypes
;------------------------------------------------------------------------------
PUBLIC _RLE_Encode
;------------------------------------------------------------------------------
; STACK SIZE
;------------------------------------------------------------------------------
.STACK 4096
;------------------------------------------------------------------------------
; RADIX TYPE
;------------------------------------------------------------------------------
; (placeholder)
;------------------------------------------------------------------------------
; DATA SEGMENT (DS)
;------------------------------------------------------------------------------
.DATA
;*********************
; EQUATES/ENUMERATORS
;*********************
; (placeholder)
;***********
; VARIABLES
;***********
; (placeholder)
;------------------------------------------------------------------------------
; CODE SEGMENT (CS)
;------------------------------------------------------------------------------
.CODE
;************
; Procedures
;************
public _RLE_Encode proc
push ebp
mov ebp, esp
push ebx
push ecx
push edx
push esi
push edi
mov esi, [ebp+8]
mov ecx, [ebp+12]
mov edi, [ebp+16]
local Outer_Loop:
mov al, [esi]
mov bl, 01h
inc esi
dec ecx
cmp ecx, 0
je Single_Byte_One
local Inner_Loop:
mov dl, [esi]
cmp al, dl
jne Single_Byte_One
inc esi
inc ebx
dec ecx
cmp bl, 3Fh
je Multiple_Byte
cmp ecx, 0
je Multiple_Byte
jmp Inner_Loop
local Multiple_Byte:
or bl, 0C0h
mov [edi], bl
inc edi
mov [edi], al
inc edi
cmp ecx, 0
je Finish
jmp Outer_Loop
local Single_Byte_Two:
mov byte ptr [edi], 0C1h
inc edi
mov [edi], al
inc edi
cmp ecx, 0
je Finish
jmp Outer_Loop
local Single_Byte_One:
cmp bl, 01h
jne Multiple_Byte
cmp al, 0Ch
jae Single_Byte_Two
mov [edi], al
inc edi
cmp ecx, 0
jne Outer_Loop
local Finish
mov eax, edi
sub eax, [ebp+16]
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop ebp
ret 12
_RLE_Encode endp
hmm.. it just says:
it can't find the file 'RLE_Encode', *
LNK 2019 unresolved external symbol _RLE_Encode referenced in function _main
LNK 1120 1 unresolved externals