See also FASM – 6502 Assembly Language Simulator – Part 1
The FASM x86 code for the 6502 assembly language simulator.
; ------------------------------------------------------------------------------------- format PE GUI 4.0 entry start include 'win32a.inc' ; ------------------------------------------------------------------------------------- IDD_EDIT_DIALOG = 102 IDD_RUN_DIALOG = 103 IDD_WATCH_DIALOG = 104 IDC_INPUT = 1000 IDC_OUTPUT = 1001 IDC_STATUS = 1002 IDC_PAGES = 1003 IDC_DEBUG = 1004 IDC_BTN_COMPILE = 1005 IDC_BTN_VIEW_ASM = 1006 IDC_BTN_VIEW_SYM = 1007 IDC_BTN_CLR_ASM = 1008 IDC_BTN_NEXT_DLG = 1009 IDC_BTN_RUN = 1010 IDC_BTN_STEP = 1011 IDC_BTN_RESET_PC = 1012 IDC_BTN_RESET = 1013 IDC_BTN_PREV_DLG = 1014 IDC_CBX_PAGE_SELECT = 1015 IDC_BTN_LOAD_ASC = 1016 IDC_BTN_ADD_WATCH = 1017 IDC_BTN_VIEW_WATCH = 1018 IDC_ASCII_IO = 1019 IDC_GRP_BOX = 1020 IDC_PROMPT_1 = 1021 IDC_PROMPT_2 = 1022 IDC_WATCH_ITEM = 1023 IDC_WATCH_NBYTES = 1024 IDC_BTN_ADD = 1025 IDC_BTN_CLOSE = 1026 ; ------------------------------------------------------------------------------------- section '.code' code readable executable start: stdcall Reset_Machine stdcall Reset_Edit_Buffers edit_dlg: invoke GetModuleHandle,0 invoke DialogBoxParam,eax,IDD_EDIT_DIALOG,0,DialogProc_Edit,0 jmp next_dlg run_dlg: invoke GetModuleHandle,0 invoke DialogBoxParam,eax,IDD_RUN_DIALOG,0,DialogProc_Run,0 next_dlg: cmp [Next_Dlg_ID],byte 0 je exit cmp [Next_Dlg_ID],byte 1 je edit_dlg cmp [Next_Dlg_ID],byte 2 je run_dlg exit: invoke ExitProcess,0 ; ------------------------------------------------------------------------------------- proc DialogProc_Edit uses esi edi ebx,hwnddlg,msg,wparam,lparam ; dialog proc for the EDIT dialog cmp [msg],WM_INITDIALOG je .wminitdialog cmp [msg],WM_COMMAND je .wmcommand cmp [msg],WM_CLOSE je .wmclose xor eax,eax jmp .quit .wminitdialog: invoke SetDlgItemText,[hwnddlg],IDC_INPUT,bfAsmCode invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfOutput jmp .done .wmcommand: cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_COMPILE je .COMPILE cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_VIEW_ASM je .VIEW_ASM cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_VIEW_SYM je .VIEW_SYM cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_CLR_ASM je .CLEAR_ASM cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_NEXT_DLG je .NEXT_DLG jmp .done .COMPILE: stdcall Reset_Watch_Arr invoke GetDlgItemText,[hwnddlg],IDC_INPUT,bfAsmCode,32768 invoke GetDlgItemText,[hwnddlg],IDC_INPUT,bfDisplay,32768 stdcall Compile cmp eax,0xffffffff je .PRINT_ERR jmp .SKIP .PRINT_ERR: stdcall Print_Compile_Error .SKIP: invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfOutput jmp .done .VIEW_ASM: invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfOutput jmp .done .VIEW_SYM: stdcall Print_Symbol_Table invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfDisplay jmp .done .CLEAR_ASM: mov [bfAsmCode],byte 0 mov [bfOutput],byte 0 invoke SetDlgItemText,[hwnddlg],IDC_INPUT,szInputText invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,"" jmp .done .NEXT_DLG: invoke EndDialog,[hwnddlg],0 mov [Next_Dlg_ID],byte 2 jmp .done .wmclose: invoke EndDialog,[hwnddlg],0 mov [Next_Dlg_ID],byte 0 .done: mov eax,1 .quit: ret endp ; ------------------------------------------------------------------------------------- proc DialogProc_Run uses esi edi ebx,hwnddlg,msg,wparam,lparam ; dialog proc for the RUN dialog locals index db 0 endl cmp [msg],WM_INITDIALOG je .wminitdialog cmp [msg],WM_COMMAND je .wmcommand cmp [msg],WM_CLOSE je .wmclose xor eax,eax jmp .quit .wminitdialog: mov byte [Watch_On],0 ; fill the combo-box invoke GetDlgItem,[hwnddlg],IDC_CBX_PAGE_SELECT mov [hCBX],eax .FILL_CB: mov cl,[index] stdcall Set_CB_String invoke SendMessage,[hCBX],CB_ADDSTRING,NULL,cbString inc byte [index] cmp [index],byte 128 jb .FILL_CB invoke SendMessage,[hCBX],CB_SETCURSEL,0,0 xor ecx,ecx xor edx,edx stdcall Print_Page invoke SetDlgItemText,[hwnddlg],IDC_PAGES,bfDisplay stdcall Print_Status invoke SetDlgItemText,[hwnddlg],IDC_STATUS,bfDisplay invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfOutput invoke SetDlgItemText,[hwnddlg],IDC_DEBUG,"" stdcall Init_ASC invoke SetDlgItemText,[hwnddlg],IDC_ASCII_IO,bfDisplay jmp .done .wmcommand: cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_RUN je .RUN cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_STEP je .STEP cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_RESET_PC je .PC cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_RESET je .RESET_MACHINE cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_PREV_DLG je .PREV_DLG cmp [wparam], CBN_SELENDOK shl 16 + IDC_CBX_PAGE_SELECT je .VIEW_PAGE cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_ADD_WATCH je .ADD_TO_WATCH cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_VIEW_WATCH je .VIEW_WATCH cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_LOAD_ASC je .LOAD_ASC jmp .done .ADD_TO_WATCH: invoke GetModuleHandle,0 invoke DialogBoxParam,eax,IDD_WATCH_DIALOG,0,DialogProc_Watch,0 ; if the bfDisplay buffer is empty, do nothing cmp byte [bfDisplay],0 je .VIEW_PAGE stdcall Add_To_Watch cmp eax,0xffffffff jne .VIEW_WATCH stdcall Print_Watch_Error invoke SetDlgItemText,[hwnddlg],IDC_PAGES,bfDisplay jmp .done .LOAD_ASC: invoke GetDlgItemText,[hwnddlg],IDC_ASCII_IO,bfDisplay,2000 stdcall Load_ASC jmp .VIEW_PAGE .VIEW_WATCH: mov byte [Watch_On],1 stdcall Print_Watch invoke SetDlgItemText,[hwnddlg],IDC_PAGES,bfDisplay stdcall Print_ASC invoke SetDlgItemText,[hwnddlg],IDC_ASCII_IO,bfDisplay jmp .done .RUN: stdcall Run cmp eax,0xffffffff je .EXE_ERROR stdcall Print_Status invoke SetDlgItemText,[hwnddlg],IDC_STATUS,bfDisplay stdcall Print_Last_Exe_Info invoke SetDlgItemText,[hwnddlg],IDC_DEBUG,bfDisplay cmp byte [Watch_On],1 je .VIEW_WATCH jmp .VIEW_PAGE .STEP: stdcall Step cmp eax,0xffffffff je .EXE_ERROR stdcall Print_Status invoke SetDlgItemText,[hwnddlg],IDC_STATUS,bfDisplay stdcall Print_Last_Exe_Info invoke SetDlgItemText,[hwnddlg],IDC_DEBUG,bfDisplay cmp byte [Watch_On],1 je .VIEW_WATCH jmp .VIEW_PAGE .PC: ; reset the program counter mov [Program_Counter],word 0x200 stdcall Print_Status invoke SetDlgItemText,[hwnddlg],IDC_STATUS,bfDisplay jmp .done .RESET_MACHINE: mov byte [Watch_On],0 stdcall Reset_Machine stdcall Reset_Watch_Arr xor ecx,ecx xor edx,edx stdcall Print_Page invoke SetDlgItemText,[hwnddlg],IDC_PAGES,bfDisplay stdcall Print_Status invoke SetDlgItemText,[hwnddlg],IDC_STATUS,bfDisplay invoke SetDlgItemText,[hwnddlg],IDC_DEBUG,"" stdcall Init_ASC invoke SetDlgItemText,[hwnddlg],IDC_ASCII_IO,bfDisplay jmp .done .VIEW_PAGE: invoke SendMessage,[hCBX],CB_GETCURSEL,0,0 mov edx,eax shl edx,9 stdcall Print_Page invoke SetDlgItemText,[hwnddlg],IDC_PAGES,bfDisplay stdcall Print_ASC invoke SetDlgItemText,[hwnddlg],IDC_ASCII_IO,bfDisplay mov byte [Watch_On],0 jmp .done .EXE_ERROR: stdcall Print_Exe_Error invoke SetDlgItemText,[hwnddlg],IDC_DEBUG,bfDisplay jmp .done .PREV_DLG: invoke EndDialog,[hwnddlg],0 mov [Next_Dlg_ID],byte 1 jmp .done .wmclose: invoke EndDialog,[hwnddlg],0 mov [Next_Dlg_ID],byte 0 .done: mov eax,1 .quit: ret endp ; ------------------------------------------------------------------------------------- proc DialogProc_Watch uses esi edi ebx,hwnddlg,msg,wparam,lparam ; dialog proc for the ADD WATCH dialog cmp [msg],WM_INITDIALOG je .wminitdialog cmp [msg],WM_COMMAND je .wmcommand cmp [msg],WM_CLOSE je .wmclose xor eax,eax jmp .quit .wminitdialog: invoke SetDlgItemText,[hwnddlg],IDC_WATCH_ITEM,"" invoke SetDlgItemText,[hwnddlg],IDC_WATCH_NBYTES,"" ; initialise bfDisplay to an empty string ; if the dialog exits and bfDisplay is still empty, do nothing lea esi,[bfDisplay] mov [esi],byte 0 jmp .done .wmcommand: cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_ADD je .ADD cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_CLOSE je .CLOSE jmp .done .ADD: lea esi,[bfDisplay] ; get the symbol or hex address invoke GetDlgItemText,[hwnddlg],IDC_WATCH_ITEM,esi,20 ; if the bfDisplay buffer is empty, just exit cmp byte [esi],0 je .CLOSE .FIND_T: cmp [esi],byte 0 je .NEXT inc esi jmp .FIND_T .NEXT: ; insert a comma between the symbol/address and the number of bytes mov [esi],byte ',' inc esi ; get the number of bytes invoke GetDlgItemText,[hwnddlg],IDC_WATCH_NBYTES,esi,10 .CLOSE: .wmclose: invoke EndDialog,[hwnddlg],0 .done: mov eax,1 .quit: ret endp ; ------------------------------------------------------------------------------------- macro PRINT_CRLF { mov [edi],byte 13 inc edi mov [edi],byte 10 inc edi } ; ------------------------------------------------------------------------------------- proc Run ; run the program lea esi,[Main_Memory] xor ecx,ecx mov cx,[Program_Counter] .LOOP: mov al,[esi+ecx] cmp al,0 je .BRK stdcall Execute_Instruction cmp eax,0xffffffff je .STOP jmp .LOOP .BRK: inc cx .STOP: mov [Program_Counter],cx ret endp ; ------------------------------------------------------------------------------------- proc Step ; execute a single instruction (pointed to by the program counter) lea esi,[Main_Memory] xor ecx,ecx mov cx,[Program_Counter] mov al,[esi+ecx] cmp al,0 je .BRK stdcall Execute_Instruction jmp .STOP .BRK: inc cx .STOP: mov [Program_Counter],cx ret endp ; ------------------------------------------------------------------------------------- proc Compile ; compile the 6502 code ; pass 1 = build the symbol table ; pass 2 = assemble the instructions stdcall Reset_Machine mov [Debug_Code],word 0 stdcall Reset_Symbol_Pointer stdcall Reset_Output ; reset the program counter mov [Program_Counter],word 0x200 .PASS_1: ; ================================================ mov [Location_Counter],word 0x200 lea esi,[bfDisplay] ; ================================================ ; Pass 1 ; get the next line .NEXT_LINE: cmp [esi],byte 0 je .PASS_2 stdcall Get_Next_Line cmp eax,0xffffffff je .DONE stdcall Check_Line cmp al,0 je .NEXT_LINE stdcall Extract_Fields cmp eax,0xffffffff je .DONE stdcall Replace_Mnemonic stdcall Process_Labels_PsOps_1 ; no further processing of the line is required if EAX = 1 cmp eax,1 je .NEXT_LINE cmp eax,0xffffffff je .DONE stdcall Get_Operand_Size cmp eax,0xffffffff je .DONE stdcall Process_Instruction cmp eax,0xffffffff je .DONE jmp .NEXT_LINE .PASS_2: ; ================================================ mov [Location_Counter],word 0x200 lea esi,[bfDisplay] ; ================================================ ; Pass 2 ; get the next line .NEXT_LINE_2: cmp [esi],byte 0 je .DONE stdcall Get_Next_Line cmp eax,0xffffffff je .DONE stdcall Check_Line cmp al,0 je .NEXT_LINE_2 stdcall Extract_Fields cmp eax,0xffffffff je .DONE stdcall Replace_Mnemonic stdcall Write_LC_To_Output cmp eax,0xffffffff je .DONE stdcall Process_Labels_PsOps_2 cmp eax,0xffffffff je .DONE ; no further processing of the line is required if EAX = 1 cmp eax,1 je .NEXT_LINE_2 stdcall Calc_Addr_Mode cmp eax,0xffffffff je .DONE stdcall Calc_Operand cmp eax,0xffffffff je .DONE stdcall Assemble_Instruction cmp eax,0xffffffff je .DONE stdcall Write_Asm_To_Output cmp eax,0xffffffff je .DONE jmp .NEXT_LINE_2 ; ================================================ .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Get_Next_Line uses edi ; get the next line from the input stream ESI ; ESI is set outside of this proc lea edi,[bfCurrentLine] xor ecx,ecx .COPY: ; copy from ESI until a null or CRLF is read mov al,[esi] cmp al,0 je .NULL_T cmp al,10 je .NEXT_LINE cmp al,13 je .NEXT_LINE cmp al,0x22 je .SUB_ASC cmp al,0x27 je .SUB_ASC ; convert all letters to upper case stdcall Char_To_Upper mov [edi],al inc esi inc edi inc cx ; if 128 chars were read, the line is too long cmp cx,128 je .ERROR jmp .COPY .SUB_ASC: ; replace a char constant (enclosed by ' ' or " ") with it's ascii code ; ascii code written as a 2 digit hex value: $xx mov [edi],byte '$' inc esi inc edi inc cx cmp cx,128 je .ERROR ; read the char mov al,[esi] cmp al,0 je .ERROR_2 ; get the ascii value stdcall Byte_To_Hex ; write the first hex digit mov [edi],ah inc edi inc cx cmp cx,128 je .ERROR ; write the second hex digit mov [edi],al inc edi inc cx cmp cx,128 je .ERROR inc esi mov al,[esi] inc esi cmp al,0x22 je .COPY cmp al,0x27 je .COPY jmp .ERROR_2 .NEXT_LINE: ; increment ESI past the CRLF inc esi mov al,[esi] cmp al,10 je .NEXT_LINE cmp al,13 je .NEXT_LINE .NULL_T: mov [edi],byte 0 lea edi,[bfCurrentLine] .DISCARD: ; if there is a comment, discard the rest of the line cmp [edi],byte 0 je .DONE cmp [edi],byte ';' jne .NEXT ; null terminate at the ';' mov [edi],byte 0 jmp .DONE .NEXT: inc edi jmp .DISCARD .ERROR: ; input line must be less than 128 chars mov eax,0xffffffff mov [Debug_Code],word 1 jmp .DONE .ERROR_2: ; invalid char in line mov eax,0xffffffff mov [Debug_Code],word 12 .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Check_Line uses esi ; is the line empty ? xor eax,eax lea esi,[bfCurrentLine] .SCAN: cmp [esi],byte 0 je .DONE cmp [esi],byte 32 jg .NOT_BLANK inc esi jmp .SCAN .NOT_BLANK: mov al,1 .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Extract_Fields uses esi edi ecx ; extract the label, mnemonic and operand from the current line lea esi,[bfCurrentLine] xor ecx,ecx ; clear the operand buffer lea edi,[bfOperand] mov [edi],byte 0 ; clear the mnemonic buffer lea edi,[bfMnemonic] mov [edi],byte 0 ; clear the label buffer lea edi,[bfLabel] mov [edi],byte 0 ; get the label (if any) ; there is a label if the first column contains a non-whitespace char cmp [esi],byte 32 jg .GET_LABEL jmp .SKIP .GET_LABEL: ; copy the label to bfLabel mov al,[esi] cmp al,0 je .NULL_T cmp al,32 je .NULL_T cmp al,9 je .NULL_T mov [edi+ecx],al inc esi inc cx ; maximum length of a label is 14 chars cmp cx,14 jg .DEBUG_1 jmp .GET_LABEL .NULL_T: mov [edi+ecx],byte 0 ; the label is now in bfLabel ; does the label contain valid chars stdcall Validate_Label cmp eax,0xffffffff je .DONE cmp [esi],byte 0 je .DONE .SKIP: ; skip any whitespace to get to the mnemonic (if any) inc esi cmp [esi],byte 9 je .SKIP cmp [esi],byte 32 je .SKIP cmp [esi],byte 0 je .DONE .GET_M: lea edi,[bfMnemonic] ; get the mnemonic ; letter 1: mov al,[esi] cmp al,'A' jl .DEBUG_2 cmp al,'Z' jg .DEBUG_2 mov [edi],al inc esi ; letter 2: mov al,[esi] cmp al,'A' jl .DEBUG_2 cmp al,'Z' jg .DEBUG_2 mov [edi+1],al inc esi ; letter 3: mov al,[esi] cmp al,'A' jl .DEBUG_2 cmp al,'Z' jg .DEBUG_2 mov [edi+2],al mov [edi+3],byte 0 inc esi ; next char in input stream must be a space or null terminator cmp [esi],byte 9 je .SKIP_2 cmp [esi],byte 32 je .SKIP_2 cmp [esi],byte 0 je .DONE jmp .DEBUG_4 .SKIP_2: ; skip any whitespace to get to the operand (if any) inc esi cmp [esi],byte 9 je .SKIP_2 cmp [esi],byte 32 je .SKIP_2 cmp [esi],byte 0 je .DONE ; get the operand lea edi,[bfOperand] xor ecx,ecx .GET_OPERAND: mov al,[esi] cmp al,0 je .NULL_T_2 cmp al,9 je .NULL_T_2 cmp al,32 je .NULL_T_2 mov [edi+ecx],al inc esi inc cx ; operand can contain a maximum of 111 chars cmp cx,111 jg .DEBUG_3 jmp .GET_OPERAND .NULL_T_2: mov [edi+ecx],byte 0 cmp al,0 je .DONE .EXTRA: ; test for extra chars on the line inc esi cmp [esi],byte 9 je .EXTRA cmp [esi],byte 32 je .EXTRA cmp [esi],byte 0 je .DONE ; if the code reaches this point there are extra chars .DEBUG_0: ; extra chars in the line mov [Debug_Code],word 2 jmp .ERROR .DEBUG_1: ; label was found to contain more than 14 chars mov [Debug_Code],word 3 jmp .ERROR .DEBUG_2: ; invalid chars in the mnemonic mov [Debug_Code],word 4 jmp .ERROR .DEBUG_3: ; operand field must be less than 112 chars mov [Debug_Code],word 5 jmp .ERROR .DEBUG_4: ; too many chars in the mnemonic field mov [Debug_Code],word 6 .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Replace_Mnemonic uses esi ; replace if the mnemonic field contains: BGE, BLT, BTR, BFL, XOR ; BGE = BCS ; BLT = BCC ; BTR = BEQ ; BFL = BNE ; XOR = EOR lea esi,[bfMnemonic] cmp [esi],byte 'B' jne .XOR cmp [esi+1],byte 'G' je .BGE cmp [esi+1],byte 'L' je .BLT cmp [esi+1],byte 'T' je .BTR cmp [esi+1],byte 'F' je .BFL jmp .DONE .BGE: cmp [esi+2],byte 'E' jne .DONE ; replace with BCS mov [esi],dword 0x00534342 jmp .DONE .BLT: cmp [esi+2],byte 'T' jne .DONE ; replace with BCC mov [esi],dword 0x00434342 jmp .DONE .BTR: cmp [esi+2],byte 'R' jne .DONE ; replace with BEQ mov [esi],dword 0x00514542 jmp .DONE .BFL: cmp [esi+2],byte 'L' jne .DONE ; replace with BNE mov [esi],dword 0x00454E42 jmp .DONE .XOR: cmp [esi],byte 'X' jne .DONE cmp [esi+1],byte 'O' jne .DONE cmp [esi+2],byte 'R' jne .DONE ; replace with EOR mov [esi],dword 0x00524F45 .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Process_Labels_PsOps_1 uses edi ecx edx ; compile = pass 1 ; check bfMnemonic for the pseudo-ops: EQU, EPZ, DFS, ORG, HEX, ADR, BYT, HBY, DBY ; put the mnemonic into EDX mov edx,dword [bfMnemonic] lea edi,[bfLabel] ; is there a mnemonic ? cmp dl,0 je .ADD_LABEL .A: cmp dl,'A' jne .B shr edx,8 cmp dl,'D' jne .ADD_LABEL shr edx,8 cmp dl,'R' jne .ADD_LABEL ; check for a label cmp [edi],byte 0 je .ADR stdcall Add_Label cmp eax,0xffffffff je .DONE .ADR: ; there must be an operand stdcall Count_Expressions cmp eax,0 je .DEBUG_3 ; reserve the bytes by incrementing the location counter ; 2 bytes for every expression shl ax,1 add [Location_Counter],ax mov eax,1 jmp .DONE .B: cmp dl,'B' jne .E shr edx,8 cmp dl,'Y' jne .ADD_LABEL shr edx,8 cmp dl,'T' jne .ADD_LABEL ; check for a label cmp [edi],byte 0 je .BYT stdcall Add_Label cmp eax,0xffffffff je .DONE .BYT: ; there must be an operand stdcall Count_Expressions cmp eax,0 je .DEBUG_3 ; reserve the bytes by incrementing the location counter ; 1 byte for every expression add [Location_Counter],ax mov eax,1 jmp .DONE .E: cmp dl,'E' jne .D shr edx,8 .EQU: ; EQU cmp dl,'Q' jne .EPZ cmp dh,'U' jne .ADD_LABEL ; there must be a label cmp [edi],byte 0 je .DEBUG_1 ; there must be an operand stdcall Count_Expressions cmp eax,0 je .DEBUG_3 stdcall Read_Number cmp eax,0xffffffff je .DONE stdcall Add_Label_EQU cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .EPZ: ; EPZ cmp dl,'P' jne .ADD_LABEL cmp dh,'Z' jne .ADD_LABEL ; there must be a label cmp [edi],byte 0 je .DEBUG_1 ; there must be an operand stdcall Count_Expressions cmp eax,0 je .DEBUG_3 stdcall Read_Number cmp eax,0xffffffff je .DONE cmp dx,255 ja .DEBUG_2 stdcall Add_Label_EQU cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .D: ; DFS cmp dl,'D' jne .H shr edx,8 cmp dl,'F' jne .DB cmp dh,'S' jne .ADD_LABEL .DFS: ; there must be a label cmp [edi],byte 0 je .DEBUG_1 stdcall Add_Label cmp eax,0xffffffff je .DONE ; there must be an operand stdcall Count_Expressions cmp eax,0 je .DEBUG_3 ; read the operand to get the number of bytes to reserve stdcall Process_DFS cmp eax,0xffffffff je .DONE ; reserve the bytes by incrementing the location counter add [Location_Counter],ax mov eax,1 jmp .DONE .DB: cmp dl,'B' jne .ADD_LABEL cmp dh,'Y' jne .ADD_LABEL ; check for a label cmp [edi],byte 0 je .DBY stdcall Add_Label cmp eax,0xffffffff je .DONE .DBY: ; there must be an operand stdcall Count_Expressions cmp eax,0 je .DEBUG_3 ; reserve the bytes by incrementing the location counter ; 2 bytes for every expression shl ax,1 add [Location_Counter],ax mov eax,1 jmp .DONE .H: cmp dl,'H' jne .O shr edx,8 cmp dl,'B' jne .HEX shr edx,8 cmp dl,'Y' jne .ADD_LABEL ; check for a label cmp [edi],byte 0 je .HBY stdcall Add_Label cmp eax,0xffffffff je .DONE .HBY: ; there must be an operand stdcall Count_Expressions cmp eax,0 je .DEBUG_3 ; reserve the bytes by incrementing the location counter ; 1 byte for every expression add [Location_Counter],ax mov eax,1 jmp .DONE .HEX: ; HEX cmp dl,'E' jne .ADD_LABEL cmp dh,'X' jne .ADD_LABEL ; check for a label cmp [edi],byte 0 je .READ_H stdcall Add_Label cmp eax,0xffffffff je .DONE .READ_H: ; there must be an operand stdcall Count_Expressions cmp eax,0 je .DEBUG_3 stdcall Read_Hex cmp eax,0xffffffff je .DONE ; increment the location counter by the number of bytes read add [Location_Counter],cx mov eax,1 jmp .DONE .O: ; ORG cmp dl,'O' jne .ADD_LABEL shr edx,8 cmp dl,'R' jne .ADD_LABEL cmp dh,'G' jne .ADD_LABEL ; check for a label cmp [edi],byte 0 je .READ_ORG stdcall Add_Label cmp eax,0xffffffff je .DONE .READ_ORG: ; there must be an operand stdcall Count_Expressions cmp eax,0 je .DEBUG_3 stdcall Process_ORG cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .ADD_LABEL: ; check for a label cmp [edi],byte 0 je .DONE stdcall Add_Label cmp eax,0xffffffff je .DONE mov eax,0 jmp .DONE .DEBUG_1: ; no label found for EQU, EPZ or DFS mov [Debug_Code],word 7 jmp .ERROR .DEBUG_2: ; operand for EPZ must evaluate to a 1 byte value mov [Debug_Code],word 8 jmp .ERROR .DEBUG_3: ; all pseudo ops must have an operand mov [Debug_Code],word 41 .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Add_Label_EQU uses esi edi ebx ecx ; add bfLabel to the symbol table and assign it the value passed in DX lea esi,[bfLabel] lea edi,[Main_Memory] ; symbol table starts on page 252 add edi,64512 xor ecx,ecx ; test against each entry in the symbol table ; pSymbol_Table points to just after the last symbol in the table mov ebx,[pSymbol_Table] ; if EBX = EDI at this point, the symbol table is empty cmp ebx,edi je .ADD .TEST: ; compare bfLabel to the entry in the symbol table mov al,[esi+ecx] cmp al,[edi+ecx] jne .NEXT cmp al,0 je .ERROR inc ecx cmp ecx,14 jle .TEST .ERROR: ; the label matches an existing symbol mov eax,0xffffffff mov [Debug_Code],word 9 jmp .DONE .NEXT: xor ecx,ecx ; entry in symbol table is 16 bytes add edi,16 cmp edi,ebx je .ADD jmp .TEST .ADD: ; add the label mov al,[esi+ecx] mov [edi+ecx],al cmp al,0 je .SET inc cx jmp .ADD .SET: mov [edi+14],dx .INCREMENT: stdcall Increment_Symbol_Pointer .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Add_Label uses esi edi ebx ecx ; add bfLabel to the symbol table lea esi,[bfLabel] lea edi,[Main_Memory] ; symbol table starts on page 252 add edi,64512 xor ecx,ecx ; test against each entry in the symbol table ; pSymbol_Table points to just after the last symbol in the table mov ebx,[pSymbol_Table] ; if EBX = EDI at this point, the symbol table is empty cmp ebx,edi je .ADD .TEST: ; compare bfLabel to the entry in the symbol table mov al,[esi+ecx] cmp al,[edi+ecx] jne .NEXT cmp al,0 je .ERROR inc ecx cmp ecx,14 jle .TEST .ERROR: ; the label matches an existing symbol mov eax,0xffffffff mov [Debug_Code],word 10 jmp .DONE .NEXT: xor ecx,ecx ; entry in symbol table is 16 bytes add edi,16 cmp edi,ebx je .ADD jmp .TEST .ADD: ; add the label mov al,[esi+ecx] mov [edi+ecx],al cmp al,0 je .SET inc cx jmp .ADD .SET: ; use the location counter to set the value of the label mov dx,[Location_Counter] mov [edi+14],dx .INCREMENT: stdcall Increment_Symbol_Pointer .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Count_Expressions uses esi ; for the ADR, DBY, BYT, HBY, DFS, ORG pseudo ops ; count the number of expressions in the operand ; return count in EAX lea esi,[bfOperand] xor eax,eax cmp [esi],byte 0 je .DONE mov eax,1 .SCAN: ; count the commas inc esi cmp [esi],byte 0 je .DONE cmp [esi],byte ',' jne .SCAN inc eax jmp .SCAN .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Process_Labels_PsOps_2 uses edi ecx edx ; compile = pass 2 ; check bfMnemonic for the pseudo-ops: EQU, EPZ, DFS, ORG, HEX, ADR, BYT, HBY, DBY lea edi,[bfMnemonic] ; put the mnemonic into EDX mov edx,[edi] lea edi,[bfLabel] ; is there a mnemonic ? cmp dl,0 ; if not, do nothing je .DONE .A: cmp dl,'A' jne .B shr edx,8 cmp dl,'D' jne .DONE shr edx,8 cmp dl,'R' jne .DONE .ADR: stdcall Process_ADR cmp eax,0xffffffff je .DONE stdcall Write_Line_To_Output cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .B: cmp dl,'B' jne .E shr edx,8 cmp dl,'Y' jne .DONE shr edx,8 cmp dl,'T' jne .DONE .BYT: stdcall Process_BYT cmp eax,0xffffffff je .DONE stdcall Write_Line_To_Output cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .E: cmp dl,'E' jne .D shr edx,8 .EQU: ; EQU cmp dl,'Q' jne .EPZ cmp dh,'U' jne .DONE ; do nothing - EQU was processed in pass 1 stdcall Write_Line_To_Output cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .EPZ: ; EPZ cmp dl,'P' jne .DONE cmp dh,'Z' jne .DONE ; do nothing - EPZ was processed in pass 1 stdcall Write_Line_To_Output cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .D: ; DFS cmp dl,'D' jne .H shr edx,8 cmp dl,'F' jne .DBY cmp dh,'S' jne .DONE ; read the operand to get the number of bytes to reserve stdcall Process_DFS cmp eax,0xffffffff je .DONE ; reserve and initialise the bytes stdcall Init_DFS stdcall Write_Line_To_Output cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .DBY: cmp dl,'B' jne .DONE cmp dh,'Y' jne .DONE stdcall Process_DBY cmp eax,0xffffffff je .DONE stdcall Write_Line_To_Output cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .H: cmp dl,'H' jne .O shr edx,8 cmp dl,'B' jne .HEX shr edx,8 cmp dl,'Y' jne .DONE .HBY: stdcall Process_HBY cmp eax,0xffffffff je .DONE stdcall Write_Line_To_Output cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .HEX: ; HEX cmp dl,'E' jne .DONE cmp dh,'X' jne .DONE .READ_H: stdcall Read_Hex cmp eax,0xffffffff je .DONE ; write the bytes to memory stdcall Store_Hex stdcall Write_Line_To_Output cmp eax,0xffffffff je .DONE mov eax,1 jmp .DONE .O: ; ORG cmp dl,'O' jne .DONE shr edx,8 cmp dl,'R' jne .DONE cmp dh,'G' jne .DONE .READ_ORG: stdcall Process_ORG cmp eax,0xffffffff je .DONE stdcall Write_Line_To_Output cmp eax,0xffffffff je .DONE mov eax,1 .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Process_ORG uses esi edi ecx ; process the ORG pseudo op ; operand contains a single expression lea esi,[bfOperand] lea edi,[bfExpression] .COPY: ; copy the expression from the operand mov al,[esi] cmp al,0 je .CALC mov [edi],al inc esi inc edi jmp .COPY .CALC: ; compute the value of the expression mov [edi],byte 0 stdcall Calc_Expression cmp eax,0xffffffff je .DONE ; set the location counter mov [Location_Counter],ax .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Process_ADR uses esi edi ecx ; process the ADR pseudo op ; operand may contain a single expression or a comma delimited list of expressions lea esi,[bfOperand] lea edi,[bfExpression] .EXTRACT: ; extract the expressions from the operand mov al,[esi] cmp al,0 je .CALC cmp al,',' je .CALC mov [edi],al inc esi inc edi jmp .EXTRACT .CALC: ; compute the value of the expression mov [edi],byte 0 stdcall Calc_Expression cmp eax,0xffffffff je .DONE ; write the 2 byte value to memory mov dx,ax mov cl,2 stdcall Store_Hex ; is there another expression ? cmp [esi],byte ',' jne .DONE inc esi lea edi,[bfExpression] jmp .EXTRACT .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Process_DBY uses esi edi ecx ; process the DBY pseudo op ; operand may contain a single expression or a comma delimited list of expressions lea esi,[bfOperand] lea edi,[bfExpression] .EXTRACT: ; extract the expressions from the operand mov al,[esi] cmp al,0 je .CALC cmp al,',' je .CALC mov [edi],al inc esi inc edi jmp .EXTRACT .CALC: ; compute the value of the expression mov [edi],byte 0 stdcall Calc_Expression cmp eax,0xffffffff je .DONE ; write the 2 byte value to memory ; high byte first mov dl,ah ; then the low byte mov dh,al mov cl,2 stdcall Store_Hex ; is there another expression ? cmp [esi],byte ',' jne .DONE inc esi lea edi,[bfExpression] jmp .EXTRACT .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Process_BYT uses esi edi ; process the BYT pseudo op ; operand may contain a single expression or a comma delimited list of expressions lea esi,[bfOperand] lea edi,[bfExpression] .EXTRACT: ; extract the expressions from the operand mov al,[esi] cmp al,0 je .CALC cmp al,',' je .CALC mov [edi],al inc esi inc edi jmp .EXTRACT .CALC: ; compute the value of the expression mov [edi],byte 0 stdcall Calc_Expression cmp eax,0xffffffff je .DONE ; write the low byte of the 2 byte value to memory mov dl,al mov cl,1 stdcall Store_Hex ; is there another expression ? cmp [esi],byte ',' jne .DONE inc esi lea edi,[bfExpression] jmp .EXTRACT .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Process_HBY uses esi edi ; process the HBY pseudo op ; operand may contain a single expression or a comma delimited list of expressions lea esi,[bfOperand] lea edi,[bfExpression] .EXTRACT: ; extract the expressions from the operand mov al,[esi] cmp al,0 je .CALC cmp al,',' je .CALC mov [edi],al inc esi inc edi jmp .EXTRACT .CALC: ; compute the value of the expression mov [edi],byte 0 stdcall Calc_Expression cmp eax,0xffffffff je .DONE ; write the high byte of the 2 byte value to memory mov dl,ah mov cl,1 stdcall Store_Hex ; is there another expression ? cmp [esi],byte ',' jne .DONE inc esi lea edi,[bfExpression] jmp .EXTRACT .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Process_DFS uses esi edi ebx ; process the DFS pseudo op ; operand can contain up to 2 expressions (comma delimited) ; first expression gives the number of bytes to reserve ; second expression gives a byte value to which the reserved bytes are initialised lea esi,[bfOperand] lea edi,[bfExpression] .EXTRACT: ; extract the first expression from the operand mov al,[esi] cmp al,0 je .CALC cmp al,',' je .CALC mov [edi],al inc esi inc edi jmp .EXTRACT .CALC: ; compute the value of the expression = number of bytes to reserve mov [edi],byte 0 stdcall Calc_Expression cmp eax,0xffffffff je .DONE ; is there another expression ? cmp [esi],byte ',' jne .DONE mov ebx,eax inc esi lea edi,[bfExpression] .EXTRACT_2: ; extract the second expression from the operand (if any) mov al,[esi] cmp al,0 je .INIT cmp al,',' je .INIT mov [edi],al inc esi inc edi jmp .EXTRACT_2 .INIT: ; the low byte value of this expression is used to init the reserved bytes mov [edi],byte 0 stdcall Calc_Expression cmp eax,0xffffffff je .DONE bswap eax mov ax,bx ; number of bytes to reserve in now in AX ; init byte value is in the upper byte of EAX .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Init_DFS uses edi ebx ecx ; init the bytes reserved by the DFS pseudo op ; the init byte value is passed in the upper byte of EAX lea edi,[Main_Memory] xor ebx,ebx mov bx,[Location_Counter] mov cx,ax ; put the byte value into AL bswap eax .INIT: mov [edi+ebx],al inc ebx dec cx cmp cx,0 je .DONE jmp .INIT .DONE: mov word [Location_Counter],bx ret endp ; ------------------------------------------------------------------------------------- proc Process_Instruction uses edi ; compile - pass 1 ; use the mnemonic and operand size to increment the location counter ; the operand size is passed in AL locals op_size db 0 addr_mode db 0 endl ; get the addressing mode stdcall Calc_Addr_Mode mov byte [addr_mode],dl ; the location counter mov cx,[Location_Counter] mov [op_size],al ; put the mnemonic into EAX mov eax,dword [bfMnemonic] ; is there anything in the mnemonic field ? cmp al,0 je .DONE lea edi,[Main_Memory] cmp al,'A' je .A cmp al,'B' je .B cmp al,'C' je .C cmp al,'D' je .D cmp al,'E' je .E cmp al,'I' je .I cmp al,'J' je .J cmp al,'L' je .L cmp al,'N' je .N cmp al,'O' je .O cmp al,'P' je .P cmp al,'R' je .R cmp al,'S' je .S cmp al,'T' je .T jmp .FAILED .A: shr eax,8 .AND: cmp al,'N' jne .ADC shr eax,8 cmp al,'D' jne .FAILED ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR ; zp,y not supported by AND, will be assembled as a,y (3 bytes) cmp byte [addr_mode],4 jne .ADD_OP_SIZE add cx,3 jmp .DONE .ADC: cmp al,'D' jne .ASL shr eax,8 cmp al,'C' jne .FAILED ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR ; zp,y not supported by ADC, will be assembled as a,y (3 bytes) cmp byte [addr_mode],4 jne .ADD_OP_SIZE add cx,3 jmp .DONE .ASL: cmp al,'S' jne .FAILED shr eax,8 cmp al,'L' jne .FAILED ; operand size can be 0, 1 or 2 bytes jmp .ADD_OP_SIZE .B: shr eax,8 .BRK: cmp al,'R' jne .BCC shr eax,8 cmp al,'K' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .BCC: cmp al,'C' jne .BIT shr eax,8 cmp al,'C' jne .BCS ; operand size should be 2 bytes cmp [op_size],byte 2 jne .ERROR ; size of assembled instruction is 2 bytes add cx,2 jmp .DONE .BCS: cmp al,'S' jne .FAILED ; operand size should be 2 bytes cmp [op_size],byte 2 jne .ERROR ; size of assembled instruction is 2 bytes add cx,2 jmp .DONE .BIT: cmp al,'I' jne .BEQ shr eax,8 cmp al,'T' jne .FAILED ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR jmp .ADD_OP_SIZE .BEQ: cmp al,'E' jne .BMI shr eax,8 cmp al,'Q' jne .FAILED ; operand size should be 2 bytes cmp [op_size],byte 2 jne .ERROR ; size of assembled instruction is 2 bytes add cx,2 jmp .DONE .BMI: cmp al,'M' jne .BNE shr eax,8 cmp al,'I' jne .FAILED ; operand size should be 2 bytes cmp [op_size],byte 2 jne .ERROR ; size of assembled instruction is 2 bytes add cx,2 jmp .DONE .BNE: cmp al,'N' jne .BPL shr eax,8 cmp al,'E' jne .FAILED ; operand size should be 2 bytes cmp [op_size],byte 2 jne .ERROR ; size of assembled instruction is 2 bytes add cx,2 jmp .DONE .BPL: cmp al,'P' jne .BVC shr eax,8 cmp al,'L' jne .FAILED ; operand size should be 2 bytes cmp [op_size],byte 2 jne .ERROR ; size of assembled instruction is 2 bytes add cx,2 jmp .DONE .BVC: cmp al,'V' jne .FAILED shr eax,8 cmp al,'C' jne .BVS ; operand size should be 2 bytes cmp [op_size],byte 2 jne .ERROR ; size of assembled instruction is 2 bytes add cx,2 jmp .DONE .BVS: cmp al,'S' jne .FAILED ; operand size should be 2 bytes cmp [op_size],byte 2 jne .ERROR ; size of assembled instruction is 2 bytes add cx,2 jmp .DONE .C: shr eax,8 .CLC: cmp al,'L' jne .CMP shr eax,8 cmp al,'C' jne .CLV ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .CLV: cmp al,'V' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .CMP: cmp al,'M' jne .CPX shr eax,8 cmp al,'P' jne .FAILED ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR ; zp,y not supported by CMP, will be assembled as a,y (3 bytes) cmp byte [addr_mode],4 jne .ADD_OP_SIZE add cx,3 jmp .DONE .CPX: cmp al,'P' jne .FAILED shr eax,8 cmp al,'X' jne .CPY ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR jmp .ADD_OP_SIZE .CPY: cmp al,'Y' jne .FAILED ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR jmp .ADD_OP_SIZE .D: shr eax,8 .DEC: cmp al,'E' jne .FAILED shr eax,8 cmp al,'C' jne .DEX ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR jmp .ADD_OP_SIZE .DEX: cmp al,'X' jne .DEY ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .DEY: cmp al,'Y' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .E: shr eax,8 .EOR: cmp al,'O' jne .FAILED shr eax,8 cmp al,'R' jne .FAILED ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR ; zp,y not supported by EOR, will be assembled as a,y (3 bytes) cmp byte [addr_mode],4 jne .ADD_OP_SIZE add cx,3 jmp .DONE .I: shr eax,8 .INC: cmp al,'N' jne .FAILED shr eax,8 cmp al,'C' jne .INX ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR jmp .ADD_OP_SIZE .INX: cmp al,'X' jne .INY ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .INY: cmp al,'Y' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .J: shr eax,8 .JMP: cmp al,'M' jne .JSR shr eax,8 cmp al,'P' jne .FAILED ; operand size cannot be 0 cmp [op_size],byte 0 je .ERROR ; size of assembled instruction is 3 bytes add cx,3 jmp .DONE .JSR: cmp al,'S' jne .FAILED shr eax,8 cmp al,'R' jne .FAILED ; operand size should be 2 bytes cmp [op_size],byte 2 jne .ERROR ; size of assembled instruction is 3 bytes add cx,3 jmp .DONE .L: shr eax,8 .LDA: cmp al,'D' jne .LSR shr eax,8 cmp al,'A' jne .LDX ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR ; zp,y not supported by LDA, will be assembled as a,y (3 bytes) cmp byte [addr_mode],4 jne .ADD_OP_SIZE add cx,3 jmp .DONE .LDX: cmp al,'X' jne .LDY ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR jmp .ADD_OP_SIZE .LDY: cmp al,'Y' jne .FAILED ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR jmp .ADD_OP_SIZE .LSR: cmp al,'S' jne .FAILED shr eax,8 cmp al,'R' jne .FAILED ; operand size can be 0, 1 or 2 bytes jmp .ADD_OP_SIZE .N: shr eax,8 .NOP: cmp al,'O' jne .FAILED shr eax,8 cmp al,'P' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .O: shr eax,8 .ORA: cmp al,'R' jne .FAILED shr eax,8 cmp al,'A' jne .FAILED ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR ; zp,y not supported by ORA, will be assembled as a,y (3 bytes) cmp byte [addr_mode],4 jne .ADD_OP_SIZE add cx,3 jmp .DONE .P: shr eax,8 .PHA: cmp al,'H' jne .PLA shr eax,8 cmp al,'A' jne .PHP ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .PHP: cmp al,'P' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .PLA: cmp al,'L' jne .FAILED shr eax,8 cmp al,'A' jne .PLP ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .PLP: cmp al,'P' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .R: shr eax,8 .ROL: cmp al,'O' jne .RTS shr eax,8 cmp al,'L' jne .ROR ; operand size can be 0, 1 or 2 bytes jmp .ADD_OP_SIZE .ROR: cmp al,'R' jne .FAILED ; operand size can be 0, 1 or 2 bytes jmp .ADD_OP_SIZE .RTS: cmp al,'T' jne .FAILED shr eax,8 cmp al,'S' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .S: shr eax,8 .STA: cmp al,'T' jne .SBC shr eax,8 cmp al,'A' jne .STX ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR ; zp,y not supported by STA, will be assembled as a,y (3 bytes) cmp byte [addr_mode],4 jne .ADD_OP_SIZE add cx,3 jmp .DONE .STX: cmp al,'X' jne .STY ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR ; a,y not supported by STX, will be assembled as zp,y (2 bytes) cmp byte [addr_mode],4 jne .ADD_OP_SIZE add cx,2 jmp .DONE .STY: cmp al,'Y' jne .FAILED ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR ; a,x not supported by STY, will be assembled as zp,x (2 bytes) cmp byte [addr_mode],3 jne .ADD_OP_SIZE add cx,2 jmp .DONE .SBC: cmp al,'B' jne .SEC shr eax,8 cmp al,'C' jne .FAILED ; operand size cannot be 0 bytes cmp [op_size],byte 0 je .ERROR ; zp,y not supported by SBC, will be assembled as a,y (3 bytes) cmp byte [addr_mode],4 jne .ADD_OP_SIZE add cx,3 jmp .DONE .SEC: cmp al,'E' jne .FAILED shr eax,8 cmp al,'C' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .T: shr eax,8 .TAX: cmp al,'A' jne .TSX shr eax,8 cmp al,'X' jne .TAY ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .TAY: cmp al,'Y' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .TSX: cmp al,'S' jne .TXA shr eax,8 cmp al,'X' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .TXA: cmp al,'X' jne .TYA shr eax,8 cmp al,'A' jne .TXS ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .TXS: cmp al,'S' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .TYA: cmp al,'Y' jne .FAILED shr eax,8 cmp al,'A' jne .FAILED ; operand size should be 0 bytes cmp [op_size],byte 0 jne .ERROR ; size of assembled instruction is 1 byte inc cx jmp .DONE .ADD_OP_SIZE: ; add the operand size to CX inc cx add cl,byte [op_size] adc ch,0 jmp .DONE .FAILED: ; unknown mnemonic mov [Debug_Code],word 17 mov eax,0xffffffff jmp .DONE .ERROR: ; invalid mnemonic and operand size combination mov [Debug_Code],word 18 mov eax,0xffffffff .DONE: mov [Location_Counter],cx ret endp ; ------------------------------------------------------------------------------------- proc Get_Operand_Size uses esi edi ecx ; determine the size of the value stored in the operand ; return in AL xor eax,eax xor ecx,ecx xor edx,edx lea esi,[bfOperand] ; is the operand empty ? cmp [esi],byte 0 je .DONE ; test the first char from ESI cmp [esi],byte '#' je .1_BYTE cmp [esi],byte '/' je .1_BYTE cmp [esi],byte '(' je .SCAN_IND .SCAN: cmp [esi],byte '*' je .2_BYTE cmp [esi],byte '$' je .SCAN_HEX cmp [esi],byte '!' je .INC_DEC cmp [esi],byte '%' je .SCAN_BIN cmp [esi],byte '0' jl .DEBUG_1 cmp [esi],byte '9' jle .SCAN_DEC cmp [esi],byte 'A' jl .DEBUG_1 cmp [esi],byte 'Z' jle .SCAN_LABEL ; the first char in the operand is an invalid char jmp .DEBUG_1 .SCAN_LABEL: ; the first char in the operand is a letter = there is a symbol lea edi,[bfSymbol] .COPY: ; read the symbol into bfSymbol mov dl,[esi] cmp dl,0 je .NULL_T cmp dl,'+' je .NULL_T cmp dl,'-' je .NULL_T cmp dl,',' je .NULL_T mov [edi],dl inc esi inc edi jmp .COPY .NULL_T: mov [edi],byte 0 ; see if there is a match for the symbol in the symbol table stdcall Lookup_Symbol ; only symbols defined with EQU or EPZ are guaranteed to ; be in the table at this point (pass 1) ; if the symbol is not in the table, then it is assumed that it will ; appear as the label for a line of code after the current line ; therefore it will have a 2 byte value cmp eax,0xffffffff je .2_BYTE ; the symbol was found, is it a ZP or absolute value ? cmp ah,0 jg .2_BYTE cmp [esi],byte 0 je .1_BYTE cmp [esi],byte ',' je .1_BYTE ; the symbol evaluates to a 1 byte value, but the argument ; after the + or - might be 2 bytes cmp [esi],byte '+' je .PLUS cmp [esi],byte '-' je .MINUS jmp .DEBUG_1 .SCAN_HEX: ; if more than 2 hex digits have been read, then it's a 2 byte value cmp cx,2 jg .2_BYTE inc esi ; it's a 1 byte value if a null, comma, plus or minus char are found here cmp [esi],byte 0 je .1_BYTE cmp [esi],byte ',' je .1_BYTE cmp [esi],byte '+' je .PLUS cmp [esi],byte '-' je .MINUS cmp [esi],byte '0' jl .DEBUG_2 cmp [esi],byte '9' jle .NEXT_H cmp [esi],byte 'A' jl .DEBUG_2 cmp [esi],byte 'F' jle .NEXT_H ; the hex number field contains an invalid char jmp .DEBUG_2 .NEXT_H: inc cx jmp .SCAN_HEX .INC_DEC: inc esi .SCAN_DEC: ; digit 1 mov dl,[esi] cmp dl,'0' jl .DEBUG_3 cmp dl,'9' jg .DEBUG_3 inc esi ; digit 2 shl edx,8 mov dl,[esi] cmp dl,0 je .1_BYTE cmp dl,',' je .1_BYTE cmp dl,'+' je .PLUS cmp dl,'-' je .MINUS cmp dl,'0' jl .DEBUG_3 cmp dl,'9' jg .DEBUG_3 inc esi ; digit 3 shl edx,8 mov dl,[esi] cmp dl,0 je .1_BYTE cmp dl,',' je .1_BYTE cmp dl,'+' je .PLUS cmp dl,'-' je .MINUS cmp dl,'0' jl .DEBUG_3 cmp dl,'9' jg .DEBUG_3 inc esi ; digit 4 cmp [esi],byte 0 je .CALC_D cmp [esi],byte '+' je .CALC_D cmp [esi],byte '-' je .CALC_D cmp [esi],byte ',' je .CALC_D shl edx,8 mov dl,[esi] cmp dl,'0' jl .DEBUG_3 cmp dl,'9' jle .2_BYTE .CALC_D: stdcall Calc_Decimal cmp edx,255 ja .2_BYTE cmp [esi],byte '+' je .PLUS cmp [esi],byte '-' je .MINUS jmp .1_BYTE .SCAN_BIN: ; if more than 8 bin digits have been read, then it's a 2 byte value cmp cx,8 jg .2_BYTE inc esi ; it's a 1 byte value if a null, comma, plus or minus char are found here cmp [esi],byte 0 je .1_BYTE cmp [esi],byte ',' je .1_BYTE cmp [esi],byte '+' je .PLUS cmp [esi],byte '-' je .MINUS cmp [esi],byte '0' je .NEXT_B cmp [esi],byte '1' je .NEXT_B ; the bin number field contains an invalid char jmp .DEBUG_4 .NEXT_B: inc cx jmp .SCAN_BIN .PLUS: inc esi xor ecx,ecx jmp .SCAN .MINUS: inc esi xor ecx,ecx jmp .SCAN .SCAN_IND: inc esi ; if a comma is found the mode is: (zp,x) or (zp),y cmp [esi],byte ',' je .1_BYTE ; if a comma is not found the mode is: (a) cmp [esi],byte 0 je .2_BYTE jmp .SCAN_IND .1_BYTE: ; operand contains a 1 byte value mov al,1 jmp .DONE .2_BYTE: ; operand contains a 2 byte value mov al,2 jmp .DONE .DEBUG_1: ; invalid char in operand mov [Debug_Code],word 12 jmp .ERROR .DEBUG_2: ; invalid char in hex number mov [Debug_Code],word 13 jmp .ERROR .DEBUG_3: ; invalid char in decimal number mov [Debug_Code],word 14 jmp .ERROR .DEBUG_4: ; invalid char in binary number mov [Debug_Code],word 15 .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Validate_Label uses esi ; the first char in a label must be a letter ; a label can only contain letters, numbers and underscores ; test the first char lea esi,[bfLabel] cmp [esi],byte 'A' jl .ERROR cmp [esi],byte 'Z' jg .ERROR .CHECK: inc esi cmp [esi],byte 0 je .DONE cmp [esi],byte '_' je .CHECK cmp [esi],byte '0' jl .ERROR cmp [esi],byte '9' jle .CHECK cmp [esi],byte 'A' jl .ERROR cmp [esi],byte 'Z' jle .CHECK .ERROR: ; label contains invalid chars mov [Debug_Code],word 16 mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Calc_Addr_Mode uses esi ; detect the addressing mode of the operand ; result is returned in DX ; addressing mode in DL ; length of operand in DH lea esi,[bfOperand] xor edx,edx .LEN: cmp [esi],byte 0 je .MODE inc dh inc esi jmp .LEN .MODE: ; test for the modes: ; ================================================ ; # = immediate (low byte) - mode = 1 ; / = immediate (high byte) - mode = 2 ; zp,x and a,x - mode = 3 ; zp,y and a,y - mode = 4 ; (zp,x) - mode = 5 ; (zp),y - mode = 6 ; (a) - mode = 7 ; all other modes - mode = 0 ; ================================================ ; is the length zero ? cmp dh,0 je .DONE lea esi,[bfOperand] ; detect immediate mode cmp [esi],byte '#' je .IMMED_LO ; detect immediate mode cmp [esi],byte '/' je .IMMED_HI ; detect indirect mode cmp [esi],byte '(' je .SCAN_2 .SCAN_1: inc esi cmp [esi],byte 0 je .DONE ; detect indexed mode cmp [esi],byte ',' je .INDEXED jmp .SCAN_1 .INDEXED: inc esi cmp [esi],byte 0 je .ERROR ; detect indexed by X mode - a,x and zp,x cmp [esi],byte 'X' jne .IS_Y mov dl,3 jmp .DONE .IS_Y: ; detect indexed by Y mode - a,y and zp,y cmp [esi],byte 'Y' jne .ERROR mov dl,4 jmp .DONE .SCAN_2: inc esi cmp [esi],byte 0 je .ERROR cmp [esi],byte ')' je .IS_IND_Y cmp [esi],byte ',' je .IS_X jmp .SCAN_2 .IS_X: inc esi ; detect indexed by X indirect mode - (zp,x) cmp [esi],byte 'X' jne .ERROR mov dl,5 jmp .DONE .IS_IND_Y: inc esi cmp [esi],byte ',' jne .INDIRECT inc esi ; detect indirect indexed by Y mode - (zp),y cmp [esi],byte 'Y' jne .INDIRECT mov dl,6 jmp .DONE .INDIRECT: ; indirect mode cmp [esi],byte 0 jne .ERROR mov dl,7 jmp .DONE .IMMED_LO: ; immediate mode (low byte) mov dl,1 jmp .DONE .IMMED_HI: ; immediate mode (high byte) mov dl,2 jmp .DONE .ERROR: mov [Debug_Code],word 31 mov eax,0xffffffff jmp .DONE .DONE: ; save the result lea esi,[Operand_Data] mov word [esi+2],dx ret endp ; ------------------------------------------------------------------------------------- proc Calc_Operand uses esi edx ; compute the 1 or 2 byte value of the operand ; an operand can have 1 or 2 arguments ; if there are 2 arguments, they must be separated by a plus or minus lea esi,[bfOperand] xor eax,eax cmp [esi],byte 0 je .DONE cmp [esi],byte '#' je .NEXT cmp [esi],byte '/' je .NEXT cmp [esi],byte '(' je .NEXT jmp .FIRST .NEXT: inc esi .FIRST: ; first argument stdcall Calc_Operand_Value cmp eax,0xffffffff je .DONE cmp [esi],byte '+' je .PLUS cmp [esi],byte '-' je .MINUS jmp .DONE .PLUS: xor edx,edx mov dx,ax inc esi ; these chars are invalid if they appear after a plus or minus sign cmp [esi],byte 0 je .ERROR cmp [esi],byte '#' je .ERROR cmp [esi],byte '/' je .ERROR cmp [esi],byte '(' je .ERROR ; second argument stdcall Calc_Operand_Value cmp eax,0xffffffff je .DONE add ax,dx jmp .DONE .MINUS: xor edx,edx mov dx,ax inc esi ; these chars are invalid if they appear after a plus or minus sign cmp [esi],byte 0 je .ERROR cmp [esi],byte '#' je .ERROR cmp [esi],byte '/' je .ERROR cmp [esi],byte '(' je .ERROR ; second argument stdcall Calc_Operand_Value cmp eax,0xffffffff je .DONE sub dx,ax mov ax,dx jmp .DONE .ERROR: ; invalid chars after a plus or minus mov [Debug_Code],word 10 mov eax,0xffffffff .DONE: ; save the result lea esi,[Operand_Data] mov [esi],ax ret endp ; ------------------------------------------------------------------------------------- proc Calc_Operand_Value ; extract an argument from the operand and calculate it's value ; an operand can have 1 or 2 arguments ; if there are 2 arguments they must be separated by a + or - ; the argument is read from ESI ; ESI is set outside of this proc ; return the 16-bit value in AX xor eax,eax .READ: cmp [esi],byte 0 je .DONE ; detect address char cmp [esi],byte '*' je .ADDR ; detect a hex number cmp [esi],byte '$' je .HEX ; detect a decimal number cmp [esi],byte '!' je .DEC ; detect a binary number cmp [esi],byte '%' je .BIN ; detect a decimal number cmp [esi],byte '0' jl .DEBUG_1 cmp [esi],byte '9' jle .DEC_1 ; detect a symbol cmp [esi],byte 'A' jl .DEBUG_1 cmp [esi],byte 'Z' jle .SYMB jmp .DEBUG_1 .NEXT: inc esi jmp .READ .HEX: inc esi stdcall Get_Hex_Value jmp .DONE .DEC: inc esi .DEC_1: stdcall Get_Dec_Value jmp .DONE .BIN: inc esi stdcall Get_Bin_Value jmp .DONE .SYMB: stdcall Get_Symbol_Value jmp .DONE .ADDR: inc esi xor eax,eax mov ax,[Location_Counter] jmp .DONE .DEBUG_1: mov [Debug_Code],word 32 mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Calc_Expression uses esi edx ; called only when processing the DFS, ADR, DBY, BYT or HBY pseudo ops ; compute the 1 or 2 byte value of an expression ; an expression can have 1 or 2 arguments ; if there are 2 arguments, they must be separated by a plus or minus ; return the result in AX lea esi,[bfExpression] xor eax,eax cmp [esi],byte 0 je .DONE ; first argument stdcall Calc_Operand_Value cmp eax,0xffffffff je .DONE cmp [esi],byte '+' je .PLUS cmp [esi],byte '-' je .MINUS jmp .DONE .PLUS: xor edx,edx mov dx,ax inc esi ; second argument stdcall Calc_Operand_Value cmp eax,0xffffffff je .DONE add ax,dx jmp .DONE .MINUS: xor edx,edx mov dx,ax inc esi ; second argument stdcall Calc_Operand_Value cmp eax,0xffffffff je .DONE sub dx,ax mov ax,dx jmp .DONE .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Get_Symbol_Value uses edi ecx ; read a symbol of up to 14 chars in length from ESI ; ESI is set outside of this proc ; symbols can only contain the chars: 0-9, A-Z and _ lea edi,[bfSymbol] ; ESI is already set to the first letter mov al,[esi] mov [edi],al inc esi inc edi mov ecx,1 .COPY: ; read the char from the input stream ESI ; stop reading when a null, ), comma, plus or minus char is found mov al,[esi] cmp al,0 je .LOOK_UP cmp al,'_' je .ADD cmp al,')' je .LOOK_UP cmp al,'+' je .LOOK_UP cmp al,'-' je .LOOK_UP cmp al,',' je .LOOK_UP cmp al,'0' jl .ERROR cmp al,'9' jle .ADD cmp al,'A' jl .ERROR cmp al,'Z' jg .ERROR .ADD: ; copy the char to bfSymbol mov [edi],al inc esi inc edi inc cx cmp cx,14 jg .ERROR jmp .COPY .LOOK_UP: ; find the symbol in the symbol table mov [edi],byte 0 stdcall Lookup_Symbol jmp .DONE .ERROR: ; could not find the symbol mov [Debug_Code],word 33 mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Lookup_Symbol uses esi edi ecx ; lookup the current symbol and get it's value ; return the result in AX lea esi,[bfSymbol] lea edi,[Main_Memory] add edi,64512 ; check if there are any symbols cmp edi,[pSymbol_Table] je .NO_MATCH xor ecx,ecx .TEST: ; test bfSymbol against the current entry in the symbol table mov al,[esi+ecx] cmp al,[edi+ecx] jne .NEXT cmp al,0 je .MATCH inc cx cmp cx,14 jl .TEST .NEXT: xor ecx,ecx ; increment the symbol pointer add edi,16 cmp edi,[pSymbol_Table] je .NO_MATCH jmp .TEST .MATCH: xor eax,eax mov ax,[edi+14] jmp .DONE .NO_MATCH: mov [Debug_Code],word 34 mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_Instruction uses edi ecx ; instruction mnemonic is put into EAX as ASCII (lower 3 bytes) ; operand data is put into EDX - length in byte 4, mode in byte 3, 16 bit value in DX mov eax,dword [bfMnemonic] mov edx,dword [Operand_Data] ; ================================================ ; # = immediate (low byte) - mode = 1 ; / = immediate (high byte) - mode = 2 ; zp,x and a,x - mode = 3 ; zp,y and a,y - mode = 4 ; (zp,x) - mode = 5 ; (zp),y - mode = 6 ; (a) - mode = 7 ; all other modes - mode = 0 ; ================================================ lea edi,[Main_Memory] xor ecx,ecx mov cx,[Location_Counter] mov [Asm_Bytes],dword 0 ; is there anything in the mnemonic field ? cmp al,0 je .DONE cmp al,'A' je .A cmp al,'B' je .B cmp al,'C' je .C cmp al,'D' je .D cmp al,'E' je .E cmp al,'I' je .I cmp al,'J' je .J cmp al,'L' je .L cmp al,'N' je .N cmp al,'O' je .O cmp al,'P' je .P cmp al,'R' je .R cmp al,'S' je .S cmp al,'T' je .T jmp .FAILED .A: shr eax,8 .AND: cmp al,'N' jne .ADC shr eax,8 cmp al,'D' jne .FAILED stdcall Assemble_AND cmp eax,0xffffffff je .ERROR_2 jmp .DONE .ADC: cmp al,'D' jne .ASL shr eax,8 cmp al,'C' jne .FAILED stdcall Assemble_ADC cmp eax,0xffffffff je .ERROR_2 jmp .DONE .ASL: cmp al,'S' jne .FAILED shr eax,8 cmp al,'L' jne .FAILED stdcall Assemble_ASL cmp eax,0xffffffff je .ERROR_2 jmp .DONE .B: shr eax,8 .BRK: cmp al,'R' jne .BCC shr eax,8 cmp al,'K' jne .FAILED mov [edi+ecx],byte 0 inc cx mov [Asm_Bytes],dword 0x01000000 jmp .DONE .BCC: cmp al,'C' jne .BIT shr eax,8 cmp al,'C' jne .BCS mov al,0x90 stdcall Assemble_Branches jmp .DONE .BCS: cmp al,'S' jne .FAILED mov al,0xB0 stdcall Assemble_Branches jmp .DONE .BIT: cmp al,'I' jne .BEQ shr eax,8 cmp al,'T' jne .FAILED stdcall Assemble_BIT cmp eax,0xffffffff je .ERROR_2 jmp .DONE .BEQ: cmp al,'E' jne .BMI shr eax,8 cmp al,'Q' jne .FAILED mov al,0xF0 stdcall Assemble_Branches jmp .DONE .BMI: cmp al,'M' jne .BNE shr eax,8 cmp al,'I' jne .FAILED mov al,0x30 stdcall Assemble_Branches jmp .DONE .BNE: cmp al,'N' jne .BPL shr eax,8 cmp al,'E' jne .FAILED mov al,0xD0 stdcall Assemble_Branches jmp .DONE .BPL: cmp al,'P' jne .BVC shr eax,8 cmp al,'L' jne .FAILED mov al,0x10 stdcall Assemble_Branches jmp .DONE .BVC: cmp al,'V' jne .FAILED shr eax,8 cmp al,'C' jne .BVS mov al,0x50 stdcall Assemble_Branches jmp .DONE .BVS: cmp al,'S' jne .FAILED mov al,0x70 stdcall Assemble_Branches jmp .DONE .C: shr eax,8 .CLC: cmp al,'L' jne .CMP shr eax,8 cmp al,'C' jne .CLV mov [edi+ecx],byte 0x18 inc cx mov [Asm_Bytes],dword 0x01000018 jmp .DONE .CLV: cmp al,'V' jne .FAILED mov [edi+ecx],byte 0xB8 inc cx mov [Asm_Bytes],dword 0x010000B8 jmp .DONE .CMP: cmp al,'M' jne .CPX shr eax,8 cmp al,'P' jne .FAILED stdcall Assemble_CMP cmp eax,0xffffffff je .ERROR_2 jmp .DONE .CPX: cmp al,'P' jne .FAILED shr eax,8 cmp al,'X' jne .CPY stdcall Assemble_CPX cmp eax,0xffffffff je .ERROR_2 jmp .DONE .CPY: cmp al,'Y' jne .FAILED stdcall Assemble_CPY cmp eax,0xffffffff je .ERROR_2 jmp .DONE .D: shr eax,8 .DEC: cmp al,'E' jne .FAILED shr eax,8 cmp al,'C' jne .DEX stdcall Assemble_DEC cmp eax,0xffffffff je .ERROR_2 jmp .DONE .DEX: cmp al,'X' jne .DEY mov [edi+ecx],byte 0xCA inc cx mov [Asm_Bytes],dword 0x010000CA jmp .DONE .DEY: cmp al,'Y' jne .FAILED mov [edi+ecx],byte 0x88 inc cx mov [Asm_Bytes],dword 0x01000088 jmp .DONE .E: shr eax,8 .EOR: cmp al,'O' jne .FAILED shr eax,8 cmp al,'R' jne .FAILED stdcall Assemble_EOR cmp eax,0xffffffff je .ERROR_2 jmp .DONE .I: shr eax,8 .INC: cmp al,'N' jne .FAILED shr eax,8 cmp al,'C' jne .INX stdcall Assemble_INC cmp eax,0xffffffff je .ERROR_2 jmp .DONE .INX: cmp al,'X' jne .INY mov [edi+ecx],byte 0xE8 inc cx mov [Asm_Bytes],dword 0x010000E8 jmp .DONE .INY: cmp al,'Y' jne .FAILED mov [edi+ecx],byte 0xC8 inc cx mov [Asm_Bytes],dword 0x010000C8 jmp .DONE .J: shr eax,8 .JMP: cmp al,'M' jne .JSR shr eax,8 cmp al,'P' jne .FAILED stdcall Assemble_JMP cmp eax,0xffffffff je .ERROR_2 jmp .DONE .JSR: cmp al,'S' jne .FAILED shr eax,8 cmp al,'R' jne .FAILED mov [edi+ecx],byte 0x20 inc cx mov [edi+ecx],dl inc cx mov [edi+ecx],dh inc cx mov [Asm_Bytes],dword 0x03000020 mov word [Asm_Bytes+1],dx shr edx,16 cmp dl,0 jne .ERROR_2 jmp .DONE .L: shr eax,8 .LDA: cmp al,'D' jne .LSR shr eax,8 cmp al,'A' jne .LDX stdcall Assemble_LDA cmp eax,0xffffffff je .ERROR_2 jmp .DONE .LDX: cmp al,'X' jne .LDY stdcall Assemble_LDX cmp eax,0xffffffff je .ERROR_2 jmp .DONE .LDY: cmp al,'Y' jne .FAILED stdcall Assemble_LDY cmp eax,0xffffffff je .ERROR_2 jmp .DONE .LSR: cmp al,'S' jne .FAILED shr eax,8 cmp al,'R' jne .FAILED stdcall Assemble_LSR cmp eax,0xffffffff je .ERROR_2 jmp .DONE .N: shr eax,8 .NOP: cmp al,'O' jne .FAILED shr eax,8 cmp al,'P' jne .FAILED mov [edi+ecx],byte 0xEA inc cx mov [Asm_Bytes],dword 0x010000EA jmp .DONE .O: shr eax,8 .ORA: cmp al,'R' jne .FAILED shr eax,8 cmp al,'A' jne .FAILED stdcall Assemble_ORA cmp eax,0xffffffff je .ERROR_2 jmp .DONE .P: shr eax,8 .PHA: cmp al,'H' jne .PLA shr eax,8 cmp al,'A' jne .PHP mov [edi+ecx],byte 0x48 inc cx mov [Asm_Bytes],dword 0x01000048 jmp .DONE .PHP: cmp al,'P' jne .FAILED mov [edi+ecx],byte 0x08 inc cx mov [Asm_Bytes],dword 0x01000008 jmp .DONE .PLA: cmp al,'L' jne .FAILED shr eax,8 cmp al,'A' jne .PLP mov [edi+ecx],byte 0x68 inc cx mov [Asm_Bytes],dword 0x01000068 jmp .DONE .PLP: cmp al,'P' jne .FAILED mov [edi+ecx],byte 0x28 inc cx mov [Asm_Bytes],dword 0x01000028 jmp .DONE .R: shr eax,8 .ROL: cmp al,'O' jne .RTS shr eax,8 cmp al,'L' jne .ROR stdcall Assemble_ROL cmp eax,0xffffffff je .ERROR_2 jmp .DONE .ROR: cmp al,'R' jne .FAILED stdcall Assemble_ROR cmp eax,0xffffffff je .ERROR_2 jmp .DONE .RTS: cmp al,'T' jne .FAILED mov [edi+ecx],byte 0x60 inc cx mov [Asm_Bytes],dword 0x01000060 jmp .DONE .S: shr eax,8 .STA: cmp al,'T' jne .SBC shr eax,8 cmp al,'A' jne .STX stdcall Assemble_STA cmp eax,0xffffffff je .ERROR_2 jmp .DONE .STX: cmp al,'X' jne .STY stdcall Assemble_STX cmp eax,0xffffffff je .ERROR_2 jmp .DONE .STY: cmp al,'Y' jne .FAILED stdcall Assemble_STY cmp eax,0xffffffff je .ERROR_2 jmp .DONE jmp .DONE .SBC: cmp al,'B' jne .SEC shr eax,8 cmp al,'C' jne .FAILED stdcall Assemble_SBC cmp eax,0xffffffff je .ERROR_2 jmp .DONE .SEC: cmp al,'E' jne .FAILED shr eax,8 cmp al,'C' jne .FAILED mov [edi+ecx],byte 0x38 inc cx mov [Asm_Bytes],dword 0x01000038 jmp .DONE .T: shr eax,8 .TAX: cmp al,'A' jne .TSX shr eax,8 cmp al,'X' jne .TAY mov [edi+ecx],byte 0xAA inc cx mov [Asm_Bytes],dword 0x010000AA jmp .DONE .TAY: cmp al,'Y' jne .FAILED mov [edi+ecx],byte 0xA8 inc cx mov [Asm_Bytes],dword 0x010000A8 jmp .DONE .TSX: cmp al,'S' jne .TXA shr eax,8 cmp al,'X' jne .FAILED mov [edi+ecx],byte 0xBA inc cx mov [Asm_Bytes],dword 0x010000BA jmp .DONE .TXA: cmp al,'X' jne .TYA shr eax,8 cmp al,'A' jne .TXS mov [edi+ecx],byte 0x8A inc cx mov [Asm_Bytes],dword 0x0100008A jmp .DONE .TXS: cmp al,'S' jne .FAILED mov [edi+ecx],byte 0x9A inc cx mov [Asm_Bytes],dword 0x0100009A jmp .DONE .TYA: cmp al,'Y' jne .FAILED shr eax,8 cmp al,'A' jne .FAILED mov [edi+ecx],byte 0x98 inc cx mov [Asm_Bytes],dword 0x01000098 jmp .DONE .FAILED: ; unknown mnemonic mov [Debug_Code],word 35 mov eax,0xffffffff jmp .DONE .ERROR_2: ; invalid addressing mode mov [Debug_Code],word 37 .DONE: mov [Location_Counter],cx ret endp ; ------------------------------------------------------------------------------------- proc Assemble_ADC ; assemble the ADC instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0x69 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x69 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZPAX mov [edi+ecx],byte 0x69 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0x69 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZPAX: ; a,x - mode = 3 cmp al,3 jne .AY cmp dh,0 je .ZPX mov [edi+ecx],byte 0x7D inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x7D mov byte [Asm_Bytes+3],3 jmp .DONE .ZPX: ; zp,x - mode = 3 mov [edi+ecx],byte 0x75 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x75 mov byte [Asm_Bytes+3],2 jmp .DONE .AY: ; a,y - mode = 4 cmp al,4 jne .ZPIX mov [edi+ecx],byte 0x79 inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x79 mov byte [Asm_Bytes+3],3 jmp .DONE .ZPIX: ; (zp,x) - mode = 5 cmp al,5 jne .ZPIY mov [edi+ecx],byte 0x61 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x61 mov byte [Asm_Bytes+3],2 jmp .DONE .ZPIY: ; (zp),y - mode = 6 cmp al,6 jne .ZP mov [edi+ecx],byte 0x71 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x71 mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x65 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x65 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x6D inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x6D mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_SBC ; assemble the SBC instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0xE9 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xE9 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZPAX mov [edi+ecx],byte 0xE9 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0xE9 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZPAX: ; a,x - mode = 3 cmp al,3 jne .AY cmp dh,0 je .ZPX mov [edi+ecx],byte 0xFD inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xFD mov byte [Asm_Bytes+3],3 jmp .DONE .ZPX: ; zp,x - mode = 3 mov [edi+ecx],byte 0xF5 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xF5 mov byte [Asm_Bytes+3],2 jmp .DONE .AY: ; a,y - mode = 4 cmp al,4 jne .ZPIX mov [edi+ecx],byte 0xF9 inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xF9 mov byte [Asm_Bytes+3],3 jmp .DONE .ZPIX: ; (zp,x) - mode = 5 cmp al,5 jne .ZPIY mov [edi+ecx],byte 0xE1 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xE1 mov byte [Asm_Bytes+3],2 jmp .DONE .ZPIY: ; (zp),y - mode = 6 cmp al,6 jne .ZP mov [edi+ecx],byte 0xF1 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xF1 mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0xE5 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xE5 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0xED inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xED mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_AND ; assemble the AND instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0x29 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x29 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZPAX mov [edi+ecx],byte 0x29 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0x29 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZPAX: ; a,x - mode = 3 cmp al,3 jne .AY cmp dh,0 je .ZPX mov [edi+ecx],byte 0x3D inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x3D mov byte [Asm_Bytes+3],3 jmp .DONE .ZPX: ; zp,x - mode = 3 mov [edi+ecx],byte 0x35 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x35 mov byte [Asm_Bytes+3],2 jmp .DONE .AY: ; a,y - mode = 4 cmp al,4 jne .ZPIX mov [edi+ecx],byte 0x39 inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x39 mov byte [Asm_Bytes+3],3 jmp .DONE .ZPIX: ; (zp,x) - mode = 5 cmp al,5 jne .ZPIY mov [edi+ecx],byte 0x21 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x21 mov byte [Asm_Bytes+3],2 jmp .DONE .ZPIY: ; (zp),y - mode = 6 cmp al,6 jne .ZP mov [edi+ecx],byte 0x31 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x31 mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x25 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x25 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x2D inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x2D mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_ORA ; assemble the ORA instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0x09 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x09 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZPAX mov [edi+ecx],byte 0x09 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0x09 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZPAX: ; a,x - mode = 3 cmp al,3 jne .AY cmp dh,0 je .ZPX mov [edi+ecx],byte 0x1D inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x1D mov byte [Asm_Bytes+3],3 jmp .DONE .ZPX: ; zp,x - mode = 3 mov [edi+ecx],byte 0x15 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x15 mov byte [Asm_Bytes+3],2 jmp .DONE .AY: ; a,y - mode = 4 cmp al,4 jne .ZPIX mov [edi+ecx],byte 0x19 inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x19 mov byte [Asm_Bytes+3],3 jmp .DONE .ZPIX: ; (zp,x) - mode = 5 cmp al,5 jne .ZPIY mov [edi+ecx],byte 0x01 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x01 mov byte [Asm_Bytes+3],2 jmp .DONE .ZPIY: ; (zp),y - mode = 6 cmp al,6 jne .ZP mov [edi+ecx],byte 0x11 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x11 mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x05 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x05 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x0D inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x0D mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_EOR ; assemble the EOR instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0x49 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x49 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZPAX mov [edi+ecx],byte 0x49 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0x49 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZPAX: ; a,x - mode = 3 cmp al,3 jne .AY cmp dh,0 je .ZPX mov [edi+ecx],byte 0x5D inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x5D mov byte [Asm_Bytes+3],3 jmp .DONE .ZPX: ; zp,x - mode = 3 mov [edi+ecx],byte 0x55 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x55 mov byte [Asm_Bytes+3],2 jmp .DONE .AY: ; a,y - mode = 4 cmp al,4 jne .ZPIX mov [edi+ecx],byte 0x59 inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x59 mov byte [Asm_Bytes+3],3 jmp .DONE .ZPIX: ; (zp,x) - mode = 5 cmp al,5 jne .ZPIY mov [edi+ecx],byte 0x41 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x41 mov byte [Asm_Bytes+3],2 jmp .DONE .ZPIY: ; (zp),y - mode = 6 cmp al,6 jne .ZP mov [edi+ecx],byte 0x51 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x51 mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x45 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x45 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x4D inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x4D mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_LDA ; assemble the LDA instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0xA9 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xA9 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZPAX mov [edi+ecx],byte 0xA9 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0xA9 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZPAX: ; a,x - mode = 3 cmp al,3 jne .AY cmp dh,0 je .ZPX mov [edi+ecx],byte 0xBD inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xBD mov byte [Asm_Bytes+3],3 jmp .DONE .ZPX: ; zp,x - mode = 3 mov [edi+ecx],byte 0xB5 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xB5 mov byte [Asm_Bytes+3],2 jmp .DONE .AY: ; a,y - mode = 4 cmp al,4 jne .ZPIX mov [edi+ecx],byte 0xB9 inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xB9 mov byte [Asm_Bytes+3],3 jmp .DONE .ZPIX: ; (zp,x) - mode = 5 cmp al,5 jne .ZPIY mov [edi+ecx],byte 0xA1 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xA1 mov byte [Asm_Bytes+3],2 jmp .DONE .ZPIY: ; (zp),y - mode = 6 cmp al,6 jne .ZP mov [edi+ecx],byte 0xB1 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xB1 mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0xA5 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xA5 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0xAD inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xAD mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_STA ; assemble the STA instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .ZPAX: ; a,x - mode = 3 cmp al,3 jne .AY cmp dh,0 je .ZPX mov [edi+ecx],byte 0x9D inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x9D mov byte [Asm_Bytes+3],3 jmp .DONE .ZPX: ; zp,x - mode = 3 mov [edi+ecx],byte 0x95 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x95 mov byte [Asm_Bytes+3],2 jmp .DONE .AY: ; a,y - mode = 4 cmp al,4 jne .ZPIX mov [edi+ecx],byte 0x99 inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x99 mov byte [Asm_Bytes+3],3 jmp .DONE .ZPIX: ; (zp,x) - mode = 5 cmp al,5 jne .ZPIY mov [edi+ecx],byte 0x81 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x81 mov byte [Asm_Bytes+3],2 jmp .DONE .ZPIY: ; (zp),y - mode = 6 cmp al,6 jne .ZP mov [edi+ecx],byte 0x91 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x91 mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x85 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x85 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x8D inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x8D mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_LDX ; assemble the LDX instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0xA2 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xA2 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZPY mov [edi+ecx],byte 0xA2 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0xA2 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZPY: ; zp,y - mode = 4 cmp al,4 jne .ZP cmp dh,0 jne .AY mov [edi+ecx],byte 0xB6 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xB6 mov byte [Asm_Bytes+3],2 jmp .DONE .AY: ; a,y - mode = 4 mov [edi+ecx],byte 0xBE inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xBE mov byte [Asm_Bytes+3],3 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0xA6 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xA6 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0xAE inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xAE mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_STX ; assemble the STX instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .ZPY: ; zp,y - mode = 4 cmp al,4 jne .ZP mov [edi+ecx],byte 0x96 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x96 mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x86 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x86 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x8E inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x8E mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_LDY ; assemble the LDY instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0xA0 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xA0 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZPX mov [edi+ecx],byte 0xA0 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0xA0 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZPX: ; zp,x - mode = 3 cmp al,3 jne .ZP cmp dh,0 jne .AX mov [edi+ecx],byte 0xB4 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xB4 mov byte [Asm_Bytes+3],2 jmp .DONE .AX: ; a,x - mode = 3 mov [edi+ecx],byte 0xBC inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xBC mov byte [Asm_Bytes+3],3 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0xA4 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xA4 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0xAC inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xAC mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_STY ; assemble the STY instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .ZPX: ; zp,x - mode = 3 cmp al,3 jne .ZP mov [edi+ecx],byte 0x94 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x94 mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x84 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x84 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x8C inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x8C mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_INC ; assemble the INC instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .ZPX: ; zp,x - mode = 3 cmp al,3 jne .ZP cmp dh,0 jne .AX mov [edi+ecx],byte 0xF6 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xF6 mov byte [Asm_Bytes+3],2 jmp .DONE .AX: ; a,x - mode = 3 mov [edi+ecx],byte 0xFE inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xFE mov byte [Asm_Bytes+3],3 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0xE6 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xE6 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0xEE inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xEE mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_DEC ; assemble the DEC instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .ZPX: ; zp,x - mode = 3 cmp al,3 jne .ZP cmp dh,0 jne .AX mov [edi+ecx],byte 0xD6 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xD6 mov byte [Asm_Bytes+3],2 jmp .DONE .AX: ; a,x - mode = 3 mov [edi+ecx],byte 0xDE inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xDE mov byte [Asm_Bytes+3],3 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0xC6 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xC6 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0xCE inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xCE mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_CMP ; assemble the CMP instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0xC9 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xC9 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZPX mov [edi+ecx],byte 0xC9 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0xC9 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZPX: ; zp,x - mode = 3 cmp al,3 jne .AY cmp dh,0 jne .AX mov [edi+ecx],byte 0xD5 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xD5 mov byte [Asm_Bytes+3],2 jmp .DONE .AX: ; a,x - mode = 3 mov [edi+ecx],byte 0xDD inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xDD mov byte [Asm_Bytes+3],3 jmp .DONE .AY: ; a,y - mode = 4 cmp al,4 jne .ZPIX mov [edi+ecx],byte 0xD9 inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xD9 mov byte [Asm_Bytes+3],3 jmp .DONE .ZPIX: ; (zp,x) - mode = 5 cmp al,5 jne .ZPIY mov [edi+ecx],byte 0xC1 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xC1 mov byte [Asm_Bytes+3],2 jmp .DONE .ZPIY: ; (zp),y - mode = 6 cmp al,6 jne .ZP mov [edi+ecx],byte 0xD1 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xD1 mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0xC5 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xC5 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0xCD inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xCD mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_CPX ; assemble the CPX instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0xE0 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xE0 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZP mov [edi+ecx],byte 0xE0 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0xE0 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0xE4 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xE4 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0xEC inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xEC mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_CPY ; assemble the CPY instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .IMMED_LO: ; immediate (low byte) - mode = 1 cmp al,1 jne .IMMED_HI mov [edi+ecx],byte 0xC0 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xC0 mov byte [Asm_Bytes+3],2 jmp .DONE .IMMED_HI: ; immediate (high byte) - mode = 2 cmp al,2 jne .ZP mov [edi+ecx],byte 0xC0 inc cx mov [edi+ecx],dh inc cx mov byte [Asm_Bytes],0xC0 mov byte [Asm_Bytes+1],dh mov byte [Asm_Bytes+3],2 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0xC4 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0xC4 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0xCC inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0xCC mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_BIT ; assemble the BIT instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x24 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x24 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x2C inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x2C mov byte [Asm_Bytes+3],3 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_ASL ; assemble the ASL instruction xor eax,eax bswap edx ; put the mode into AL mov al,dh ; is the length of the operand zero ? cmp dl,0 je .ACC bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .ZPX: ; zp,x - mode = 3 cmp al,3 jne .ZP cmp dh,0 jne .AX mov [edi+ecx],byte 0x16 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x16 mov byte [Asm_Bytes+3],2 jmp .DONE .AX: ; a,x - mode = 3 mov [edi+ecx],byte 0x1E inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x1E mov byte [Asm_Bytes+3],3 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x06 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x06 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x0E inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x0E mov byte [Asm_Bytes+3],3 jmp .DONE .ACC: ; accumulator mode cmp al,0 jne .ERROR mov [edi+ecx],byte 0x0A inc cx mov byte [Asm_Bytes],0x0A mov byte [Asm_Bytes+3],1 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_LSR ; assemble the LSR instruction xor eax,eax bswap edx ; put the mode into AL mov al,dh ; is the length of the operand zero ? cmp dl,0 je .ACC bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .ZPX: ; zp,x - mode = 3 cmp al,3 jne .ZP cmp dh,0 jne .AX mov [edi+ecx],byte 0x56 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x56 mov byte [Asm_Bytes+3],2 jmp .DONE .AX: ; a,x - mode = 3 mov [edi+ecx],byte 0x5E inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x5E mov byte [Asm_Bytes+3],3 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x46 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x46 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x4E inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x4E mov byte [Asm_Bytes+3],3 jmp .DONE .ACC: ; accumulator mode cmp al,0 jne .ERROR mov [edi+ecx],byte 0x4A inc cx mov byte [Asm_Bytes],0x4A mov byte [Asm_Bytes+3],1 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_ROL ; assemble the ROL instruction xor eax,eax bswap edx ; put the mode into AL mov al,dh ; is the length of the operand zero ? cmp dl,0 je .ACC bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .ZPX: ; zp,x - mode = 3 cmp al,3 jne .ZP cmp dh,0 jne .AX mov [edi+ecx],byte 0x36 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x36 mov byte [Asm_Bytes+3],2 jmp .DONE .AX: ; a,x - mode = 3 mov [edi+ecx],byte 0x3E inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x3E mov byte [Asm_Bytes+3],3 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x26 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x26 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x2E inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x2E mov byte [Asm_Bytes+3],3 jmp .DONE .ACC: ; accumulator mode cmp al,0 jne .ERROR mov [edi+ecx],byte 0x2A inc cx mov byte [Asm_Bytes],0x2A mov byte [Asm_Bytes+3],1 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_ROR ; assemble the ROR instruction xor eax,eax bswap edx ; put the mode into AL mov al,dh ; is the length of the operand zero ? cmp dl,0 je .ACC bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx .ZPX: ; zp,x - mode = 3 cmp al,3 jne .ZP cmp dh,0 jne .AX mov [edi+ecx],byte 0x76 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x76 mov byte [Asm_Bytes+3],2 jmp .DONE .AX: ; a,x - mode = 3 mov [edi+ecx],byte 0x7E inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x7E mov byte [Asm_Bytes+3],3 jmp .DONE .ZP: ; zp - mode = 0 cmp al,0 jne .ERROR cmp dh,0 jne .ABS mov [edi+ecx],byte 0x66 inc cx mov [edi+ecx],dl inc cx mov byte [Asm_Bytes],0x66 mov byte [Asm_Bytes+3],2 jmp .DONE .ABS: ; a - mode = 0 mov [edi+ecx],byte 0x6E inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x6E mov byte [Asm_Bytes+3],3 jmp .DONE .ACC: ; accumulator mode cmp al,0 jne .ERROR mov [edi+ecx],byte 0x6A inc cx mov byte [Asm_Bytes],0x6A mov byte [Asm_Bytes+3],1 jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_JMP ; assemble the JMP instruction xor eax,eax ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; put the mode into AL mov al,dh bswap edx ; the operand data is in DX mov word [Asm_Bytes+1],dx mov byte [Asm_Bytes+3],3 .ABS: ; a - mode = 0 cmp al,0 jne .IND mov [edi+ecx],byte 0x4C inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x4C jmp .DONE .IND: ; (a) - mode = 7 cmp al,7 jne .ERROR mov [edi+ecx],byte 0x6C inc cx mov [edi+ecx],dx add cx,2 mov byte [Asm_Bytes],0x6C jmp .DONE .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Assemble_Branches ; assemble the branch instructions ; BPL, BMI, BVC, BVS, BCC, BCS, BNE, BEQ ; the op code is passed in AL ; is the length of the operand zero ? bswap edx cmp dl,0 je .ERROR ; check the mode cmp dh,0 jne .ERROR bswap edx ; the operand data is in DX mov byte [Asm_Bytes],al mov byte [Asm_Bytes+3],2 ; calculate the relative offset sub dx,2 sub dx,cx ; check for out of range errors: .LT: ; for DX > CX ; (i) DH != 0 ; (ii) DH = 0 and DL = 80 cmp dh,0 jne .GT cmp dl,0x80 je .ERROR jmp .OP .GT: ; for DX < CX ; (i) DH != FF ; (ii) DH = FF and DL < 80 cmp dh,0xff jne .ERROR cmp dl,0x80 jb .ERROR .OP: ; write the op code mov [edi+ecx],al inc cx ; write the relative offset mov [edi+ecx],dl inc cx xor eax,eax mov byte [Asm_Bytes+1],dl jmp .DONE .ERROR: mov [Debug_Code],word 36 mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- macro GET_BYTE_IMMED { ; the op code byte has just been read - increment the program counter (CX) inc cx ; read the data byte mov al,[esi+ecx] ; increment CX to the next instruction inc cx } ; ------------------------------------------------------------------------------------- macro GET_BYTE_ABS { ; the op code byte has just been read - increment the program counter (CX) inc cx xor edx,edx ; read the address of the data into DX mov dx,[esi+ecx] mov word [Exe_Info_67],dx ; increment CX to the next instruction add cx,2 ; read the data byte mov al,[esi+edx] } ; ------------------------------------------------------------------------------------- macro GET_BYTE_ZP { ; the op code byte has just been read - increment the program counter (CX) inc cx xor edx,edx ; read the ZP address of the data into DL mov dl,[esi+ecx] mov word [Exe_Info_67],dx ; increment CX to the next instruction inc cx ; read the data byte mov al,[esi+edx] } ; ------------------------------------------------------------------------------------- macro GET_BYTE_AX { ; the op code byte has just been read - increment the program counter (CX) inc cx xor edx,edx ; read the address of the data into DX mov dx,[esi+ecx] ; increment CX to the next instruction add cx,2 ; index the address of the data by the value of the X register add dl,[Index_Reg_X] adc dh,0 mov word [Exe_Info_67],dx ; read the data byte mov al,[esi+edx] } ; ------------------------------------------------------------------------------------- macro GET_BYTE_AY { ; the op code byte has just been read - increment the program counter (CX) inc cx xor edx,edx ; read the address of the data into DX mov dx,[esi+ecx] ; increment CX to the next instruction add cx,2 ; index the address of the data by the value of the Y register add dl,[Index_Reg_Y] adc dh,0 mov word [Exe_Info_67],dx ; read the data byte mov al,[esi+edx] } ; ------------------------------------------------------------------------------------- macro GET_BYTE_ZPX { ; the op code byte has just been read - increment the program counter (CX) inc cx xor edx,edx ; read the ZP address of the data into DL mov dl,[esi+ecx] ; increment CX to the next instruction inc cx ; index the address of the data by the value of the X register add dl,[Index_Reg_X] mov word [Exe_Info_67],dx ; read the data byte mov al,[esi+edx] } ; ------------------------------------------------------------------------------------- macro GET_BYTE_ZPY { ; the op code byte has just been read - increment the program counter (CX) inc cx xor edx,edx ; read the ZP address of the data into DL mov dl,[esi+ecx] ; increment CX to the next instruction inc cx ; index the address of the data by the value of the Y register add dl,[Index_Reg_Y] mov word [Exe_Info_67],dx ; read the data byte mov al,[esi+edx] } ; ------------------------------------------------------------------------------------- macro GET_BYTE_ZPIX { ; the op code byte has just been read - increment the program counter (CX) inc cx xor edx,edx ; get the byte that stores the zero page address mov dl,[esi+ecx] ; increment CX to the next instruction inc cx ; add X to the zero page address (result wraps to a zero page address) add dl,[Index_Reg_X] ; read the 2 byte target address stored at the zero page address mov dx,[esi+edx] mov word [Exe_Info_67],dx ; read the data byte mov al,[esi+edx] } ; ------------------------------------------------------------------------------------- macro GET_BYTE_ZPIY { ; the op code byte has just been read - increment the program counter (CX) inc cx xor edx,edx ; get the byte that stores the zero page address of the target address mov dl,[esi+ecx] ; increment CX to the next instruction inc cx ; read the 2 byte target address stored at the zero page address mov dx,[esi+edx] ; add Y to the target address add dl,[Index_Reg_Y] adc dh,0 mov word [Exe_Info_67],dx ; read the data byte mov al,[esi+edx] } ; ------------------------------------------------------------------------------------- proc Execute_Instruction ; execute the instruction stdcall Reset_Exe_Info mov word [Exe_Info],cx ; the op code byte is passed in AL cmp al,0 je .DONE cmp al,0x69 je .ADC_69 cmp al,0x6D je .ADC_6D cmp al,0x65 je .ADC_65 cmp al,0x7D je .ADC_7D cmp al,0x79 je .ADC_79 cmp al,0x75 je .ADC_75 cmp al,0x61 je .ADC_61 cmp al,0x71 je .ADC_71 cmp al,0xE9 je .SBC_E9 cmp al,0xED je .SBC_ED cmp al,0xE5 je .SBC_E5 cmp al,0xFD je .SBC_FD cmp al,0xF9 je .SBC_F9 cmp al,0xF5 je .SBC_F5 cmp al,0xE1 je .SBC_E1 cmp al,0xF1 je .SBC_F1 cmp al,0x29 je .AND_29 cmp al,0x2D je .AND_2D cmp al,0x25 je .AND_25 cmp al,0x3D je .AND_3D cmp al,0x39 je .AND_39 cmp al,0x35 je .AND_35 cmp al,0x21 je .AND_21 cmp al,0x31 je .AND_31 cmp al,0x09 je .ORA_09 cmp al,0x0D je .ORA_0D cmp al,0x05 je .ORA_05 cmp al,0x1D je .ORA_1D cmp al,0x19 je .ORA_19 cmp al,0x15 je .ORA_15 cmp al,0x01 je .ORA_01 cmp al,0x11 je .ORA_11 cmp al,0x49 je .EOR_49 cmp al,0x4D je .EOR_4D cmp al,0x45 je .EOR_45 cmp al,0x5D je .EOR_5D cmp al,0x59 je .EOR_59 cmp al,0x55 je .EOR_55 cmp al,0x41 je .EOR_41 cmp al,0x51 je .EOR_51 cmp al,0x0A je .ASL_0A cmp al,0x0E je .ASL_0E cmp al,0x06 je .ASL_06 cmp al,0x1E je .ASL_1E cmp al,0x16 je .ASL_16 cmp al,0x4A je .LSR_4A cmp al,0x4E je .LSR_4E cmp al,0x46 je .LSR_46 cmp al,0x5E je .LSR_5E cmp al,0x56 je .LSR_56 cmp al,0x2A je .ROL_2A cmp al,0x2E je .ROL_2E cmp al,0x26 je .ROL_26 cmp al,0x3E je .ROL_3E cmp al,0x36 je .ROL_36 cmp al,0x6A je .ROR_6A cmp al,0x6E je .ROR_6E cmp al,0x66 je .ROR_66 cmp al,0x7E je .ROR_7E cmp al,0x76 je .ROR_76 cmp al,0xA9 je .LDA_A9 cmp al,0xAD je .LDA_AD cmp al,0xA5 je .LDA_A5 cmp al,0xBD je .LDA_BD cmp al,0xB9 je .LDA_B9 cmp al,0xB5 je .LDA_B5 cmp al,0xA1 je .LDA_A1 cmp al,0xB1 je .LDA_B1 cmp al,0x8D je .STA_8D cmp al,0x85 je .STA_85 cmp al,0x9D je .STA_9D cmp al,0x99 je .STA_99 cmp al,0x95 je .STA_95 cmp al,0x81 je .STA_81 cmp al,0x91 je .STA_91 cmp al,0xA2 je .LDX_A2 cmp al,0xAE je .LDX_AE cmp al,0xA6 je .LDX_A6 cmp al,0xBE je .LDX_BE cmp al,0xB6 je .LDX_B6 cmp al,0xA0 je .LDY_A0 cmp al,0xAC je .LDY_AC cmp al,0xA4 je .LDY_A4 cmp al,0xBC je .LDY_BC cmp al,0xB4 je .LDY_B4 cmp al,0x8E je .STX_8E cmp al,0x86 je .STX_86 cmp al,0x96 je .STX_96 cmp al,0x8C je .STY_8C cmp al,0x84 je .STY_84 cmp al,0x94 je .STY_94 cmp al,0xC9 je .CMP_C9 cmp al,0xCD je .CMP_CD cmp al,0xC5 je .CMP_C5 cmp al,0xDD je .CMP_DD cmp al,0xD9 je .CMP_D9 cmp al,0xD5 je .CMP_D5 cmp al,0xC1 je .CMP_C1 cmp al,0xD1 je .CMP_D1 cmp al,0xE0 je .CPX_E0 cmp al,0xEC je .CPX_EC cmp al,0xE4 je .CPX_E4 cmp al,0xC0 je .CPY_C0 cmp al,0xCC je .CPY_CC cmp al,0xC4 je .CPY_C4 cmp al,0x24 je .BIT_24 cmp al,0x2C je .BIT_2C cmp al,0xEE je .INC_EE cmp al,0xE6 je .INC_E6 cmp al,0xFE je .INC_FE cmp al,0xF6 je .INC_F6 cmp al,0xCE je .DEC_CE cmp al,0xC6 je .DEC_C6 cmp al,0xDE je .DEC_DE cmp al,0xD6 je .DEC_D6 cmp al,0xE8 je .INX_E8 cmp al,0xCA je .DEX_CA cmp al,0xC8 je .INY_C8 cmp al,0x88 je .DEY_88 cmp al,0x4C je .JMP_4C cmp al,0x6C je .JMP_6C cmp al,0x48 je .PHA_48 cmp al,0x68 je .PLA_68 cmp al,0x08 je .PHP_08 cmp al,0x28 je .PLP_28 cmp al,0xAA je .TAX_AA cmp al,0x8A je .TXA_8A cmp al,0xA8 je .TAY_A8 cmp al,0x98 je .TYA_98 cmp al,0xBA je .TSX_BA cmp al,0x9A je .TXS_9A cmp al,0x18 je .CLC_18 cmp al,0x38 je .SEC_38 cmp al,0xB8 je .CLV_B8 cmp al,0xEA je .NOP_EA cmp al,0x20 je .JSR_20 cmp al,0x60 je .RTS_60 cmp al,0x10 je .BPL_10 cmp al,0x30 je .BMI_30 cmp al,0x50 je .BVC_50 cmp al,0x70 je .BVS_70 cmp al,0x90 je .BCC_90 cmp al,0xB0 je .BCS_B0 cmp al,0xD0 je .BNE_D0 cmp al,0xF0 je .BEQ_F0 jmp .ERROR .ADC_69: ; ADC - immediate mode GET_BYTE_IMMED xor ah,ah mov word [Exe_Info_89],ax stdcall ADC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x03434441 jmp .DONE .ADC_6D: ; ADC - absolute mode GET_BYTE_ABS stdcall ADC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x04434441 jmp .DONE .ADC_65: ; ADC - zero page mode GET_BYTE_ZP stdcall ADC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x05434441 jmp .DONE .ADC_7D: ; ADC - absolute indexed with X mode GET_BYTE_AX stdcall ADC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x06434441 jmp .DONE .ADC_79: ; ADC - absolute indexed with Y mode GET_BYTE_AY stdcall ADC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x07434441 jmp .DONE .ADC_75: ; ADC - zero page indexed with X mode GET_BYTE_ZPX stdcall ADC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x08434441 jmp .DONE .ADC_61: ; ADC - indexed by X indirect mode GET_BYTE_ZPIX stdcall ADC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x0a434441 jmp .DONE .ADC_71: ; ADC - indirect indexed by Y mode GET_BYTE_ZPIY stdcall ADC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x0b434441 jmp .DONE .SBC_E9: ; SBC - immediate mode GET_BYTE_IMMED xor ah,ah mov word [Exe_Info_89],ax stdcall SBC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x03434253 jmp .DONE .SBC_ED: ; SBC - absolute mode GET_BYTE_ABS stdcall SBC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x04434253 jmp .DONE .SBC_E5: ; SBC - zero page mode GET_BYTE_ZP stdcall SBC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x05434253 jmp .DONE .SBC_FD: ; SBC - absolute indexed with X mode GET_BYTE_AX stdcall SBC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x06434253 jmp .DONE .SBC_F9: ; SBC - absolute indexed with Y mode GET_BYTE_AY stdcall SBC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x07434253 jmp .DONE .SBC_F5: ; SBC - zero page indexed with X mode GET_BYTE_ZPX stdcall SBC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x08434253 jmp .DONE .SBC_E1: ; SBC - indexed by X indirect mode GET_BYTE_ZPIX stdcall SBC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x0a434253 jmp .DONE .SBC_F1: ; SBC - indirect indexed by Y mode GET_BYTE_ZPIY stdcall SBC_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x0b434253 jmp .DONE .AND_29: ; AND - immediate mode GET_BYTE_IMMED xor ah,ah mov word [Exe_Info_89],ax and al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x03444e41 jmp .DONE .AND_2D: ; AND - absolute mode GET_BYTE_ABS and al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x04444e41 jmp .DONE .AND_25: ; AND - zero page mode GET_BYTE_ZP and al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x05444e41 jmp .DONE .AND_3D: ; AND - absolute indexed with X mode GET_BYTE_AX and al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x06444e41 jmp .DONE .AND_39: ; AND - absolute indexed with Y mode GET_BYTE_AY and al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x07444e41 jmp .DONE .AND_35: ; AND - zero page indexed with X mode GET_BYTE_ZPX and al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x08444e41 jmp .DONE .AND_21: ; AND - indexed by X indirect mode GET_BYTE_ZPIX and al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0a444e41 jmp .DONE .AND_31: ; AND - indirect indexed by Y mode GET_BYTE_ZPIY and al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0b444e41 jmp .DONE .ORA_09: ; ORA - immediate mode GET_BYTE_IMMED xor ah,ah mov word [Exe_Info_89],ax or al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0341524f jmp .DONE .ORA_0D: ; ORA - absolute mode GET_BYTE_ABS or al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0441524f jmp .DONE .ORA_05: ; ORA - zero page mode GET_BYTE_ZP or al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0541524f jmp .DONE .ORA_1D: ; ORA - absolute indexed with X mode GET_BYTE_AX or al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0641524f jmp .DONE .ORA_19: ; ORA - absolute indexed with Y mode GET_BYTE_AY or al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0741524f jmp .DONE .ORA_15: ; ORA - zero page indexed with X mode GET_BYTE_ZPX or al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0841524f jmp .DONE .ORA_01: ; ORA - indexed by X indirect mode GET_BYTE_ZPIX or al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0a41524f jmp .DONE .ORA_11: ; ORA - indirect indexed by Y mode GET_BYTE_ZPIY or al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0b41524f jmp .DONE .EOR_49: ; EOR - immediate mode GET_BYTE_IMMED xor ah,ah mov word [Exe_Info_89],ax xor al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x03524f45 jmp .DONE .EOR_4D: ; EOR - absolute mode GET_BYTE_ABS xor al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x04524f45 jmp .DONE .EOR_45: ; EOR - zero page mode GET_BYTE_ZP xor al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x05524f45 jmp .DONE .EOR_5D: ; EOR - absolute indexed with X mode GET_BYTE_AX xor al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x06524f45 jmp .DONE .EOR_59: ; EOR - absolute indexed with Y mode GET_BYTE_AY xor al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x07524f45 jmp .DONE .EOR_55: ; EOR - zero page indexed with X mode GET_BYTE_ZPX xor al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x08524f45 jmp .DONE .EOR_41: ; EOR - indexed by X indirect mode GET_BYTE_ZPIX xor al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0a524f45 jmp .DONE .EOR_51: ; EOR - indirect indexed by Y mode GET_BYTE_ZPIY xor al,[Accumulator] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0b524f45 jmp .DONE .ASL_0A: ; ASL - accumulator mode inc cx mov al,[Accumulator] stdcall ASL_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x004c5341 jmp .DONE .ASL_0E: ; ASL - absolute mode GET_BYTE_ABS stdcall ASL_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x044c5341 jmp .DONE .ASL_06: ; ASL - zero page mode GET_BYTE_ZP stdcall ASL_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x054c5341 jmp .DONE .ASL_1E: ; ASL - absolute indexed with X mode GET_BYTE_AX stdcall ASL_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x064c5341 jmp .DONE .ASL_16: ; ASL - zero page indexed with X mode GET_BYTE_ZPX stdcall ASL_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x084c5341 jmp .DONE .LSR_4A: ; LSR - accumulator mode inc cx mov al,[Accumulator] stdcall LSR_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x0052534c jmp .DONE .LSR_4E: ; LSR - absolute mode GET_BYTE_ABS stdcall LSR_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x0452534c jmp .DONE .LSR_46: ; LSR - zero page mode GET_BYTE_ZP stdcall LSR_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x0552534c jmp .DONE .LSR_5E: ; LSR - absolute indexed with X mode GET_BYTE_AX stdcall LSR_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x0652534c jmp .DONE .LSR_56: ; LSR - zero page indexed with X mode GET_BYTE_ZPX stdcall LSR_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x0852534c jmp .DONE .ROL_2A: ; ROL - accumulator mode inc cx mov al,[Accumulator] stdcall ROL_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x004c4f52 jmp .DONE .ROL_2E: ; ROL - absolute mode GET_BYTE_ABS stdcall ROL_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x044c4f52 jmp .DONE .ROL_26: ; ROL - zero page mode GET_BYTE_ZP stdcall ROL_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x054c4f52 jmp .DONE .ROL_3E: ; ROL - absolute indexed with X mode GET_BYTE_AX stdcall ROL_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x064c4f52 jmp .DONE .ROL_36: ; ROL - zero page indexed with X mode GET_BYTE_ZPX stdcall ROL_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x084c4f52 jmp .DONE .ROR_6A: ; ROR - accumulator mode inc cx mov al,[Accumulator] stdcall ROR_Byte mov [Accumulator],al mov dword [Exe_Info_2345],0x00524f52 jmp .DONE .ROR_6E: ; ROR - absolute mode GET_BYTE_ABS stdcall ROR_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x04524f52 jmp .DONE .ROR_66: ; ROR - zero page mode GET_BYTE_ZP stdcall ROR_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x05524f52 jmp .DONE .ROR_7E: ; ROR - absolute indexed with X mode GET_BYTE_AX stdcall ROR_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x06524f52 jmp .DONE .ROR_76: ; ROR - zero page indexed with X mode GET_BYTE_ZPX stdcall ROR_Byte mov [esi+edx],al mov dword [Exe_Info_2345],0x08524f52 jmp .DONE .LDA_A9: ; LDA - immediate mode GET_BYTE_IMMED stdcall Set_ZN xor ah,ah mov word [Exe_Info_89],ax mov [Accumulator],al mov dword [Exe_Info_2345],0x0341444c jmp .DONE .LDA_AD: ; LDA - absolute mode GET_BYTE_ABS stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0441444c jmp .DONE .LDA_A5: ; LDA - zero page mode GET_BYTE_ZP stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0541444c jmp .DONE .LDA_BD: ; LDA - absolute indexed with X mode GET_BYTE_AX stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0641444c jmp .DONE .LDA_B9: ; LDA - absolute indexed with Y mode GET_BYTE_AY stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0741444c jmp .DONE .LDA_B5: ; LDA - zero page indexed with X mode GET_BYTE_ZPX stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0841444c jmp .DONE .LDA_A1: ; LDA - indexed by X indirect mode GET_BYTE_ZPIX stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0a41444c jmp .DONE .LDA_B1: ; LDA - indirect indexed by Y mode GET_BYTE_ZPIY stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x0b41444c jmp .DONE .STA_8D: ; STA - absolute mode inc cx xor edx,edx mov dx,[esi+ecx] mov word [Exe_Info_67],dx add cx,2 mov al,[Accumulator] mov [esi+edx],al mov dword [Exe_Info_2345],0x04415453 jmp .DONE .STA_85: ; STA - zero page mode inc cx xor edx,edx mov dl,[esi+ecx] mov word [Exe_Info_67],dx inc cx mov al,[Accumulator] mov [esi+edx],al mov dword [Exe_Info_2345],0x05415453 jmp .DONE .STA_9D: ; STA - absolute indexed with X mode inc cx xor edx,edx mov dx,[esi+ecx] add cx,2 add dl,[Index_Reg_X] adc dh,0 mov word [Exe_Info_67],dx mov al,[Accumulator] mov [esi+edx],al mov dword [Exe_Info_2345],0x06415453 jmp .DONE .STA_99: ; STA - absolute indexed with Y mode inc cx xor edx,edx mov dx,[esi+ecx] add cx,2 add dl,[Index_Reg_Y] adc dh,0 mov al,[Accumulator] mov word [Exe_Info_67],dx mov [esi+edx],al mov dword [Exe_Info_2345],0x07415453 jmp .DONE .STA_95: ; STA - zero page indexed with X mode inc cx xor edx,edx mov dl,[esi+ecx] add dl,[Index_Reg_X] mov word [Exe_Info_67],dx inc cx mov al,[Accumulator] mov [esi+edx],al mov dword [Exe_Info_2345],0x08415453 jmp .DONE .STA_81: ; STA - indexed by X indirect mode inc cx xor edx,edx ; get the byte that stores the zero page address mov dl,[esi+ecx] inc cx ; add X to the zero page address (result wraps to a zero page address) add dl,[Index_Reg_X] ; read the 2 byte target address stored at the zero page address mov dx,[esi+edx] mov word [Exe_Info_67],dx ; do the STA operation mov al,[Accumulator] ; set the byte at the target address mov [esi+edx],al mov dword [Exe_Info_2345],0x0a415453 jmp .DONE .STA_91: ; STA - indirect indexed by Y mode inc cx xor edx,edx ; get the byte that stores the zero page address of the target address mov dl,[esi+ecx] inc cx ; read the 2 byte target address stored at the zero page address mov dx,[esi+edx] ; add Y to the target address add dl,[Index_Reg_Y] adc dh,0 mov word [Exe_Info_67],dx ; do the STA operation mov al,[Accumulator] ; set the byte at the target address mov [esi+edx],al mov dword [Exe_Info_2345],0x0b415453 jmp .DONE .LDX_A2: ; LDX - immediate mode GET_BYTE_IMMED stdcall Set_ZN xor ah,ah mov word [Exe_Info_89],ax mov [Index_Reg_X],al mov dword [Exe_Info_2345],0x0358444c jmp .DONE .LDX_AE: ; LDX - absolute mode GET_BYTE_ABS stdcall Set_ZN mov [Index_Reg_X],al mov dword [Exe_Info_2345],0x0458444c jmp .DONE .LDX_A6: ; LDX - zero page mode GET_BYTE_ZP stdcall Set_ZN mov [Index_Reg_X],al mov dword [Exe_Info_2345],0x0558444c jmp .DONE .LDX_BE: ; LDX - absolute indexed with Y mode GET_BYTE_AY stdcall Set_ZN mov [Index_Reg_X],al mov dword [Exe_Info_2345],0x0758444c jmp .DONE .LDX_B6: ; LDX - zero page indexed with Y mode GET_BYTE_ZPY stdcall Set_ZN mov [Index_Reg_X],al mov dword [Exe_Info_2345],0x0958444c jmp .DONE .LDY_A0: ; LDY - immediate mode GET_BYTE_IMMED stdcall Set_ZN xor ah,ah mov word [Exe_Info_89],ax mov [Index_Reg_Y],al mov dword [Exe_Info_2345],0x0359444c jmp .DONE .LDY_AC: ; LDY - absolute mode GET_BYTE_ABS stdcall Set_ZN mov [Index_Reg_Y],al mov dword [Exe_Info_2345],0x0459444c jmp .DONE .LDY_A4: ; LDY - zero page mode GET_BYTE_ZP stdcall Set_ZN mov [Index_Reg_Y],al mov dword [Exe_Info_2345],0x0559444c jmp .DONE .LDY_BC: ; LDY - absolute indexed with X mode GET_BYTE_AX stdcall Set_ZN mov [Index_Reg_Y],al mov dword [Exe_Info_2345],0x0659444c jmp .DONE .LDY_B4: ; LDY - zero page indexed with X mode GET_BYTE_ZPX stdcall Set_ZN mov [Index_Reg_Y],al mov dword [Exe_Info_2345],0x0859444c jmp .DONE .STX_8E: ; STX - absolute mode inc cx xor edx,edx mov dx,[esi+ecx] mov word [Exe_Info_67],dx add cx,2 mov al,[Index_Reg_X] mov [esi+edx],al mov dword [Exe_Info_2345],0x04585453 jmp .DONE .STX_86: ; STX - zero page mode inc cx xor edx,edx mov dl,[esi+ecx] mov word [Exe_Info_67],dx inc cx mov al,[Index_Reg_X] mov [esi+edx],al mov dword [Exe_Info_2345],0x05585453 jmp .DONE .STX_96: ; STX - zero page indexed with Y mode inc cx xor edx,edx mov dl,[esi+ecx] add dl,[Index_Reg_Y] mov word [Exe_Info_67],dx inc cx mov al,[Index_Reg_X] mov [esi+edx],al mov dword [Exe_Info_2345],0x09585453 jmp .DONE .STY_8C: ; STY - absolute mode inc cx xor edx,edx mov dx,[esi+ecx] mov word [Exe_Info_67],dx add cx,2 mov al,[Index_Reg_Y] mov [esi+edx],al mov dword [Exe_Info_2345],0x04595453 jmp .DONE .STY_84: ; STY - zero page mode inc cx xor edx,edx mov dl,[esi+ecx] mov word [Exe_Info_67],dx inc cx mov al,[Index_Reg_Y] mov [esi+edx],al mov dword [Exe_Info_2345],0x05595453 jmp .DONE .STY_94: ; STY - zero page indexed with X mode inc cx xor edx,edx mov dl,[esi+ecx] add dl,[Index_Reg_X] mov word [Exe_Info_67],dx inc cx mov al,[Index_Reg_Y] mov [esi+edx],al mov dword [Exe_Info_2345],0x08595453 jmp .DONE .CMP_C9: ; CMP - immediate mode GET_BYTE_IMMED xor ah,ah mov word [Exe_Info_89],ax stdcall CMP_Byte mov dword [Exe_Info_2345],0x03504d43 jmp .DONE .CMP_CD: ; CMP - absolute mode GET_BYTE_ABS stdcall CMP_Byte mov dword [Exe_Info_2345],0x04504d43 jmp .DONE .CMP_C5: ; CMP - zero page mode GET_BYTE_ZP stdcall CMP_Byte mov dword [Exe_Info_2345],0x05504d43 jmp .DONE .CMP_DD: ; CMP - absolute indexed with X mode GET_BYTE_AX stdcall CMP_Byte mov dword [Exe_Info_2345],0x06504d43 jmp .DONE .CMP_D9: ; CMP - absolute indexed with Y mode GET_BYTE_AY stdcall CMP_Byte mov dword [Exe_Info_2345],0x07504d43 jmp .DONE .CMP_D5: ; CMP - zero page indexed with X mode GET_BYTE_ZPX stdcall CMP_Byte mov dword [Exe_Info_2345],0x08504d43 jmp .DONE .CMP_C1: ; CMP - indexed by X indirect mode GET_BYTE_ZPIX ; do the CMP operation stdcall CMP_Byte mov dword [Exe_Info_2345],0x0a504d43 jmp .DONE .CMP_D1: ; CMP - indirect indexed by Y mode GET_BYTE_ZPIY ; do the CMP operation stdcall CMP_Byte mov dword [Exe_Info_2345],0x0b504d43 jmp .DONE .CPX_E0: ; CPX - immediate mode GET_BYTE_IMMED xor ah,ah mov word [Exe_Info_89],ax stdcall CPX_Byte mov dword [Exe_Info_2345],0x03585043 jmp .DONE .CPX_EC: ; CPX - absolute mode GET_BYTE_ABS stdcall CPX_Byte mov dword [Exe_Info_2345],0x04585043 jmp .DONE .CPX_E4: ; CPX - zero page mode GET_BYTE_ZP stdcall CPX_Byte mov dword [Exe_Info_2345],0x05585043 jmp .DONE .CPY_C0: ; CPY - immediate mode GET_BYTE_IMMED xor ah,ah mov word [Exe_Info_89],ax stdcall CPY_Byte mov dword [Exe_Info_2345],0x03595043 jmp .DONE .CPY_CC: ; CPY - absolute mode GET_BYTE_ABS stdcall CPY_Byte mov dword [Exe_Info_2345],0x04595043 jmp .DONE .CPY_C4: ; CPY - zero page mode GET_BYTE_ZP stdcall CPY_Byte mov dword [Exe_Info_2345],0x05595043 jmp .DONE .BIT_24: ; BIT - zero page mode GET_BYTE_ZP stdcall Test_BIT mov dword [Exe_Info_2345],0x05544942 jmp .DONE .BIT_2C: ; BIT - absolute mode GET_BYTE_ABS stdcall Test_BIT mov dword [Exe_Info_2345],0x04544942 jmp .DONE .INC_EE: ; INC - absolute mode GET_BYTE_ABS inc al stdcall Set_ZN mov [esi+edx],al mov dword [Exe_Info_2345],0x04434e49 jmp .DONE .INC_E6: ; INC - zero page mode GET_BYTE_ZP inc al stdcall Set_ZN mov [esi+edx],al mov dword [Exe_Info_2345],0x05434e49 jmp .DONE .INC_FE: ; INC - absolute indexed with X mode GET_BYTE_AX inc al stdcall Set_ZN mov [esi+edx],al mov dword [Exe_Info_2345],0x06434e49 jmp .DONE .INC_F6: ; INC - zero page indexed with X mode GET_BYTE_ZPX inc al stdcall Set_ZN mov [esi+edx],al mov dword [Exe_Info_2345],0x08434e49 jmp .DONE .DEC_CE: ; DEC - absolute mode GET_BYTE_ABS dec al stdcall Set_ZN mov [esi+edx],al mov dword [Exe_Info_2345],0x04434544 jmp .DONE .DEC_C6: ; DEC - zero page mode GET_BYTE_ZP dec al stdcall Set_ZN mov [esi+edx],al mov dword [Exe_Info_2345],0x05434544 jmp .DONE .DEC_DE: ; DEC - absolute indexed with X mode GET_BYTE_AX dec al stdcall Set_ZN mov [esi+edx],al mov dword [Exe_Info_2345],0x06434544 jmp .DONE .DEC_D6: ; DEC - zero page indexed with X mode GET_BYTE_ZPX dec al stdcall Set_ZN mov [esi+edx],al mov dword [Exe_Info_2345],0x08434544 jmp .DONE .INX_E8: ; INX - implied mode inc cx mov al,[Index_Reg_X] inc al stdcall Set_ZN mov [Index_Reg_X],al mov dword [Exe_Info_2345],0x01584e49 jmp .DONE .DEX_CA: ; DEX - implied mode inc cx mov al,[Index_Reg_X] dec al stdcall Set_ZN mov [Index_Reg_X],al mov dword [Exe_Info_2345],0x01584544 jmp .DONE .INY_C8: ; INY - implied mode inc cx mov al,[Index_Reg_Y] inc al stdcall Set_ZN mov [Index_Reg_Y],al mov dword [Exe_Info_2345],0x01594e49 jmp .DONE .DEY_88: ; DEY - implied mode inc cx mov al,[Index_Reg_Y] dec al stdcall Set_ZN mov [Index_Reg_Y],al mov dword [Exe_Info_2345],0x01594544 jmp .DONE .JMP_4C: ; JMP - absolute mode inc cx xor edx,edx ; get the target address mov dx,[esi+ecx] mov word [Exe_Info_67],dx add cx,2 ; load the target address into the program counter (CX) mov cx,dx mov dword [Exe_Info_2345],0x04504d4a jmp .DONE .JMP_6C: ; JMP - indirect mode inc cx xor edx,edx ; get the address of the target address mov dx,[esi+ecx] add cx,2 ; get the target address mov dx,[esi+edx] mov word [Exe_Info_67],dx ; load the target address into the program counter (CX) mov cx,dx mov dword [Exe_Info_2345],0x0c504d4a jmp .DONE .PHA_48: ; PHA - implied mode ; push Acc to the stack inc cx mov al,[Accumulator] stdcall Push_Byte mov dword [Exe_Info_2345],0x01414850 jmp .DONE .PLA_68: ; PLA - implied mode ; pull Acc from the stack inc cx stdcall Pull_Byte stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x01414c50 jmp .DONE .PHP_08: ; PHP - implied mode ; push NV_ZC (the processor status) to the stack inc cx mov al,[NV_ZC] stdcall Push_Byte mov dword [Exe_Info_2345],0x01504850 jmp .DONE .PLP_28: ; PLP - implied mode ; pull NV_ZC (the processor status) from the stack inc cx stdcall Pull_Byte mov [NV_ZC],al mov dword [Exe_Info_2345],0x01504c50 jmp .DONE .TAX_AA: ; TAX - implied mode ; set X = ACC inc cx mov al,[Accumulator] stdcall Set_ZN mov [Index_Reg_X],al mov dword [Exe_Info_2345],0x01584154 jmp .DONE .TXA_8A: ; TXA - implied mode ; set ACC = X inc cx mov al,[Index_Reg_X] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x01415854 jmp .DONE .TAY_A8: ; TAY - implied mode ; set Y = ACC inc cx mov al,[Accumulator] stdcall Set_ZN mov [Index_Reg_Y],al mov dword [Exe_Info_2345],0x01594154 jmp .DONE .TYA_98: ; TYA - implied mode ; set ACC = Y inc cx mov al,[Index_Reg_Y] stdcall Set_ZN mov [Accumulator],al mov dword [Exe_Info_2345],0x01415954 jmp .DONE .TSX_BA: ; TSX - implied mode ; set X = Stack_Pointer inc cx mov al,[Stack_Pointer] stdcall Set_ZN mov [Index_Reg_X],al mov dword [Exe_Info_2345],0x01585354 jmp .DONE .TXS_9A: ; TXS - implied mode ; set Stack_Pointer = X inc cx mov al,[Index_Reg_X] mov [Stack_Pointer],al mov dword [Exe_Info_2345],0x01535854 jmp .DONE .CLC_18: ; CLC - clear the carry flag inc cx and [NV_ZC],byte 0xfe mov dword [Exe_Info_2345],0x01434c43 jmp .DONE .SEC_38: ; SEC - set the carry flag inc cx or [NV_ZC],byte 1 mov dword [Exe_Info_2345],0x01434553 jmp .DONE .CLV_B8: ; CLV - clear the overflow flag inc cx and [NV_ZC],byte 0x8f mov dword [Exe_Info_2345],0x01564c43 jmp .DONE .NOP_EA: ; NOP - do nothing - just increment CX inc cx mov dword [Exe_Info_2345],0x01504f4e jmp .DONE .JSR_20: ; JSR - absolute mode inc cx xor edx,edx ; get the address to jump to mov dx,[esi+ecx] mov word [Exe_Info_67],dx inc cx ; get the return address minus 1 mov ax,cx ; push the return address minus 1 to the stack ; high byte mov al,ah stdcall Push_Byte ; low byte mov ax,cx stdcall Push_Byte ; set the program counter to the target address (DX) mov cx,dx mov dword [Exe_Info_2345],0x0452534a jmp .DONE .RTS_60: ; pull the return address minus 1 from the stack ; low byte stdcall Pull_Byte mov cl,al ; high byte stdcall Pull_Byte mov ch,al ; increment the program counter inc cx mov dword [Exe_Info_2345],0x01535452 jmp .DONE .BPL_10: ; BPL - relative mode ; branch if N = 0 mov dword [Exe_Info_2345],0x024c5042 ; put the relative offset into AL GET_BYTE_IMMED ; test N mov dl,[NV_ZC] and dl,0x80 jnz .DONE stdcall Add_Relative jmp .DONE .BMI_30: ; BMI - relative mode ; branch if N = 1 mov dword [Exe_Info_2345],0x02494d42 ; put the relative offset into AL GET_BYTE_IMMED ; test N mov dl,[NV_ZC] and dl,0x80 jz .DONE stdcall Add_Relative jmp .DONE .BVC_50: ; BVC - relative mode ; branch if V = 0 mov dword [Exe_Info_2345],0x02435642 ; put the relative offset into AL GET_BYTE_IMMED ; test V mov dl,[NV_ZC] and dl,0x40 jnz .DONE stdcall Add_Relative jmp .DONE .BVS_70: ; BVS - relative mode ; branch if V = 1 mov dword [Exe_Info_2345],0x02535642 ; put the relative offset into AL GET_BYTE_IMMED ; test V mov dl,[NV_ZC] and dl,0x40 jz .DONE stdcall Add_Relative jmp .DONE .BCC_90: ; BCC - relative mode ; branch if C = 0 mov dword [Exe_Info_2345],0x02434342 ; put the relative offset into AL GET_BYTE_IMMED ; test C mov dl,[NV_ZC] and dl,1 jnz .DONE stdcall Add_Relative jmp .DONE .BCS_B0: ; BCS - relative mode ; branch if C = 1 mov dword [Exe_Info_2345],0x02534342 ; put the relative offset into AL GET_BYTE_IMMED ; test C mov dl,[NV_ZC] and dl,1 jz .DONE stdcall Add_Relative jmp .DONE .BNE_D0: ; BNE - relative mode ; branch if Z = 0 mov dword [Exe_Info_2345],0x02454e42 ; put the relative offset into AL GET_BYTE_IMMED ; test Z mov dl,[NV_ZC] and dl,2 jnz .DONE stdcall Add_Relative jmp .DONE .BEQ_F0: ; BEQ - relative mode ; branch if Z = 1 mov dword [Exe_Info_2345],0x02514542 ; put the relative offset into AL GET_BYTE_IMMED ; test Z mov dl,[NV_ZC] and dl,2 jz .DONE stdcall Add_Relative jmp .DONE .ERROR: ; unknown instruction mov byte [Debug_Code],al mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc ASL_Byte ; shift left AL by 1 bit and set the CZN flags ; clear the C flag and [NV_ZC],byte 0xfe shl al,1 jnc .ZN ; set the C flag or [NV_ZC],byte 1 .ZN: stdcall Set_ZN ret endp ; ------------------------------------------------------------------------------------- proc LSR_Byte ; shift right AL by 1 bit and set the CZN flags ; clear the C flag and [NV_ZC],byte 0xfe shr al,1 jnc .ZN ; set the C flag or [NV_ZC],byte 1 .ZN: stdcall Set_ZN ret endp ; ------------------------------------------------------------------------------------- proc ROL_Byte ; rotate left AL by 1 bit (through the C bit) and set the CZN flags ; store the C flag in AH mov ah,byte [NV_ZC] and ah,1 ; clear the C flag and [NV_ZC],byte 0xfe ; shift left shl al,1 jnc .NC ; set the C flag or [NV_ZC],byte 1 .NC: ; complete the ROL by adding the bit that was stored in the C flag or al,ah .ZN: stdcall Set_ZN ret endp ; ------------------------------------------------------------------------------------- proc ROR_Byte ; rotate right AL by 1 bit (through the C bit) and set the CZN flags ; store the C flag in AH mov ah,byte [NV_ZC] and ah,1 ; clear the C flag and [NV_ZC],byte 0xfe ; shift right shr al,1 jnc .NC ; set the C flag or [NV_ZC],byte 1 .NC: ; complete the ROL by adding the bit that was stored in the C flag ror ah,1 or al,ah .ZN: stdcall Set_ZN ret endp ; ------------------------------------------------------------------------------------- proc CMP_Byte uses ebx ; compare the byte passed in AL to the accumulator mov bl,byte [Accumulator] ; clear the C flag and [NV_ZC],byte 0xfe ; CMP = BL - AL cmp bl,al jl .ZN ; set the C flag or byte [NV_ZC],1 .ZN: ; set the Z and N flags sub bl,al ; put the result back into AL mov al,bl stdcall Set_ZN ret endp ; ------------------------------------------------------------------------------------- proc CPX_Byte uses ebx ; compare the byte passed in AL to the X register mov bl,byte [Index_Reg_X] ; clear the C flag and [NV_ZC],byte 0xfe ; CPX = BL - AL cmp bl,al jl .ZN ; set the C flag or byte [NV_ZC],1 .ZN: ; set the Z and N flags sub bl,al ; put the result back into AL mov al,bl stdcall Set_ZN ret endp ; ------------------------------------------------------------------------------------- proc CPY_Byte uses ebx ; compare the byte passed in AL to the Y register mov bl,byte [Index_Reg_Y] ; clear the C flag and [NV_ZC],byte 0xfe ; CPY = BL - AL cmp bl,al jl .ZN ; set the C flag or byte [NV_ZC],1 .ZN: ; set the Z and N flags sub bl,al ; put the result back into AL mov al,bl stdcall Set_ZN ret endp ; ------------------------------------------------------------------------------------- proc ADC_Byte uses ebx ; to the accumulator: add the byte in AL and the C bit ; the result is returned in AL ; save the C bit to BL mov bl,byte [NV_ZC] ; clear the V and C bits and [NV_ZC],byte 0x82 ; use the value of BL to set the x86 carry bit clc and bl,1 jz .ADD stc .ADD: ; copy the accumulator to BL mov bl,byte [Accumulator] ; ADC to AL adc al,bl ; set the V and C bits pushfw pop bx and bl,1 or [NV_ZC],bl mov bl,bh and bl,8 shl bl,3 or [NV_ZC],bl .ZN: ; set the Z and N flags (based on the value of AL) stdcall Set_ZN ret endp ; ------------------------------------------------------------------------------------- proc SBC_Byte ; subtract the byte in AL from the accumulator ; calculate as: ACC + not(AL) + C ; the result is returned in AL ; put the value of the accumulator into AH mov ah,byte [Accumulator] ; invert AL xor al,0xFF ; save the C bit to BL mov bl,byte [NV_ZC] ; clear the V and C bits and [NV_ZC],byte 0x82 ; use the value of BL to set the x86 carry bit clc and bl,1 jz .SUB stc .SUB: ; ADC the bytes AL and AH adc al,ah ; set the V and C bits pushfw pop bx and bl,1 or [NV_ZC],bl mov bl,bh and bl,8 shl bl,3 or [NV_ZC],bl .ZN: ; set the Z and N flags (based on the value of AL) stdcall Set_ZN ret endp ; ------------------------------------------------------------------------------------- proc Add_Relative ; add or subtract the offset in AL to the program counter (CX) mov ah,0 mov dl,al and dl,0x80 jnz .SUB .ADD: add cx,ax jmp .DONE .SUB: mov ah,0xff add cx,ax .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Test_BIT ; test the value in AL against the Accumulator ; for the 6502 BIT operation ; set the flags mov dl,[NV_ZC] ; C is unaffected and dl,1 ; set N to bit 7 of AL ; set V to bit 6 of AL mov ah,al and ah,0xc0 or dl,ah ; AND to set the Z flag mov ah,[Accumulator] and al,ah cmp al,0 je .DONE or dl,2 .DONE: mov [NV_ZC],dl ret endp ; ------------------------------------------------------------------------------------- proc Push_Byte uses edi edx ; push a byte to the stack ; the byte is passed in AL lea edi,[Main_Memory] xor edx,edx mov dl,[Stack_Pointer] add edx,0x100 ; push the byte to the stack mov [edi+edx],al ; decrement the stack pointer dec dl ; update the stack pointer mov [Stack_Pointer],dl ret endp ; ------------------------------------------------------------------------------------- proc Pull_Byte uses edi edx ; pull a byte from the stack ; the byte is returned in AL lea edi,[Main_Memory] xor edx,edx mov dl,[Stack_Pointer] ; increment the stack pointer inc dl ; update the stack pointer mov [Stack_Pointer],dl ; pull the byte from the stack add edx,0x100 mov al,[edi+edx] ret endp ; ------------------------------------------------------------------------------------- proc Set_ZN ; set the flags Z and N based on the value of AL ; clear Z and N and [NV_ZC],byte 0x41 .Z: cmp al,0 jne .N or [NV_ZC],byte 2 .N: mov ah,al and ah,0x80 cmp ah,0 je .DONE or [NV_ZC],byte 0x80 .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Reset_Machine ; reset all memory and registers to zero lea edi,[Main_Memory] xor ecx,ecx .CLEAR: mov [edi],dword 0 add edi,4 inc cx cmp cx,16384 jl .CLEAR ; clear the registers mov [Accumulator],byte 0 mov [Index_Reg_X],byte 0 mov [Index_Reg_Y],byte 0 mov [Stack_Pointer],byte 0xff mov [NV_ZC],byte 0 mov [Program_Counter],word 0x200 mov [Location_Counter],word 0x200 stdcall Reset_Symbol_Pointer ret endp ; ------------------------------------------------------------------------------------- proc Reset_Edit_Buffers ; reset the edit buffers lea esi,[szInputText] lea edi,[bfAsmCode] .COPY: mov al,[esi] cmp al,0 je .DONE mov [edi],al inc esi inc edi jmp .COPY .DONE: mov [edi],byte 0 mov [bfOutput],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Print_Page uses ebx ; print the 512 bytes of the two currently selected pages of memory lea edi,[bfDisplay] lea esi,[Main_Memory] ; offset from start of memory in bytes passed in EDX add esi,edx xor ecx,ecx ; print the address of the row (in DX) mov al,dh stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov al,dl stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],dword 0x20203A20 add edi,4 .PRINT: stdcall Byte_To_Ascii mov [edi],byte 32 inc edi inc cx cmp cx,256 jne .CRLF ; print an extra CRLF after the first 256 bytes PRINT_CRLF .CRLF: ; print a CRLF after every 16 bytes mov bx,cx and bx,15 cmp bx,0 jg .NEXT PRINT_CRLF ; print the address of the row (in DX) cmp cx,512 je .NULL_T add edx,16 mov al,dh stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov al,dl stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],dword 0x20203A20 add edi,4 .NEXT: inc esi cmp cx,512 jl .PRINT .NULL_T: ; NULL terminate bfDisplay mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Print_Status ; print the status of the registers lea edi,[bfDisplay] mov [edi],dword "Regi" add edi,4 mov [edi],dword "ster" add edi,4 mov [edi],word "s:" add edi,2 PRINT_CRLF PRINT_CRLF ; accumulator mov [edi],dword "ACC " add edi,4 mov [edi],word 0x203a add edi,2 lea esi,[Accumulator] stdcall Byte_To_Ascii PRINT_CRLF ; index register X mov [edi],dword "IRX " add edi,4 mov [edi],word 0x203a add edi,2 lea esi,[Index_Reg_X] stdcall Byte_To_Ascii PRINT_CRLF ; index register y mov [edi],dword "IRY " add edi,4 mov [edi],word 0x203a add edi,2 lea esi,[Index_Reg_Y] stdcall Byte_To_Ascii PRINT_CRLF ; stack pointer mov [edi],dword "SP " add edi,4 mov [edi],word 0x203a add edi,2 lea esi,[Stack_Pointer] stdcall Byte_To_Ascii PRINT_CRLF ; NZ_VC - print as binary digits mov [edi],dword "NVZC" add edi,4 mov [edi],word 0x203a add edi,2 lea esi,[NV_ZC] xor eax,eax mov al,[esi] mov ah,al ; the C flag and al,1 add al,48 ; the Z flag shr ah,1 and ah,1 add ah,48 bswap eax mov al,[esi] mov ah,al ; the N flag shr al,7 and al,1 add al,48 ; the V flag shr ah,6 and ah,1 add ah,48 mov [edi],eax add edi,4 PRINT_CRLF ; program counter mov [edi],dword "PC " add edi,4 mov [edi],word 0x203a add edi,2 lea esi,[Program_Counter] inc esi stdcall Byte_To_Ascii dec esi stdcall Byte_To_Ascii PRINT_CRLF ; NULL terminate bfDisplay mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Byte_To_Ascii ; convert a byte to 2 ASCII chars ; read the byte from ESI ; write the ASCII chars to EDI mov al,[esi] ; put the low nibble into AL and the high nibble into AH mov ah,al and al,0xf shr ah,4 and ah,0xf ; convert the low nibble to an ASCII char .AL_09: cmp al,9 jg .AL_AF add al,'0' jmp .AH_09 .AL_AF: sub al,10 add al,'A' ; convert the high nibble to an ASCII char .AH_09: cmp ah,9 jg .AH_AF add ah,'0' jmp .DONE .AH_AF: sub ah,10 add ah,'A' .DONE: mov [edi],ah inc edi mov [edi],al inc edi ret endp ; ------------------------------------------------------------------------------------- proc Byte_To_Hex ; convert a byte to 2 hex digits ; read the byte from AL ; write the hex digits to AX ; put the low nibble into AL and the high nibble into AH mov ah,al and al,0xf shr ah,4 and ah,0xf ; convert the low nibble to a hex digit .AL_09: cmp al,9 jg .AL_AF add al,'0' jmp .AH_09 .AL_AF: sub al,10 add al,'A' ; convert the high nibble to a hex digit .AH_09: cmp ah,9 jg .AH_AF add ah,'0' jmp .DONE .AH_AF: sub ah,10 add ah,'A' .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Set_CB_String ; set the combo-box string ; index is in CL (0-127) ; index 0 = pages 0-1 ; index 1 = pages 2-3 ; and so on lea edi,[cbString] mov [edi],dword "Page" add edi,4 mov [edi],dword "s: " add edi,4 mov dl,cl shl dl,1 stdcall Byte_To_Decimal bswap eax mov [edi],eax add edi,4 mov [edi],byte '-' inc edi mov dl,cl shl dl,1 inc dl stdcall Byte_To_Decimal bswap eax mov [edi],eax add edi,4 mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Byte_To_Decimal ; byte is in DL - result returned in EAX xor eax,eax ; digit 4 = always zero mov ah,48 ; digit 3 = hundreds (0,1,2) mov al,48 cmp dl,200 jb .100 sub dl,200 mov al,50 jmp .NEXT .100: cmp dl,100 jb .NEXT sub dl,100 mov al,49 .NEXT: shl eax,16 mov ah,48 ; digit 2 = tens .10: cmp dl,10 jb .1 sub dl,10 inc ah jmp .10 .1: mov al,dl add al,48 ret endp ; ------------------------------------------------------------------------------------- proc Calc_Decimal uses eax ebx ; up to 4 decimal digits are passed in EDX ; return value in DX ; called by proc Get_Operand_Size xor eax,eax xor ebx,ebx ; digit 1: mov al,dl cmp al,0 je .DONE sub al,'0' ; digit 2 shr edx,8 cmp dl,0 je .DONE sub dl,'0' ; multiply EAX by 10 mov ebx,eax shl ebx,3 shl eax,1 add eax,ebx ; add the value of the digit xor ebx,ebx mov bl,dl add eax,ebx ; digit 3 shr edx,8 cmp dl,0 je .DONE sub dl,'0' ; multiply EAX by 10 mov ebx,eax shl ebx,3 shl eax,1 add eax,ebx ; add the value of the digit xor ebx,ebx mov bl,dl add eax,ebx ; digit 4 shr edx,8 cmp dl,0 je .DONE sub dl,'0' ; multiply EAX by 10 mov ebx,eax shl ebx,3 shl eax,1 add eax,ebx ; add the value of the digit xor ebx,ebx mov bl,dl add eax,ebx .DONE: mov edx,eax ret endp ; ------------------------------------------------------------------------------------- proc Read_Number uses esi ebx ecx ; read a number from bfOperand ; can be binary, decimal or hex ; return a 2 byte value in DX ; called by proc Process_Labels_PsOps_1 and proc Process_Labels_PsOps_2 xor edx,edx lea esi,[bfOperand] xor ecx,ecx ; detect a hex number ? cmp [esi],byte '$' je .HEX ; detect a binary number ? cmp [esi],byte '%' je .BIN ; detect a decimal number ? cmp [esi],byte '!' je .NEXT_D ; assume that the number is decimal: jmp .DEC .HEX: ; hex - read a maximum of 4 hex digits inc esi mov bl,[esi] cmp bl,0 je .DONE cmp bl,'0' jl .DEBUG_1 cmp bl,'9' jle .ADD_09 cmp bl,'A' jl .DEBUG_1 cmp bl,'F' jle .ADD_AF jmp .DEBUG_1 .ADD_09: ; add the digit to EDX (0-9) shl edx,4 sub bl,'0' or dl,bl jmp .NEXT_H .ADD_AF: ; add the digit to EDX (A-F) shl edx,4 sub bl,'A' add bl,10 or dl,bl .NEXT_H: inc cx ; read a maximum of 4 hex digits cmp cx,4 jg .DEBUG_2 jmp .HEX .BIN: ; binary - read a maximum of 16 binary digits inc esi mov bl,[esi] cmp bl,0 je .DONE shl edx,1 cmp bl,'0' je .NEXT_B cmp bl,'1' jne .DEBUG_3 or edx,1 .NEXT_B: inc cx ; read a maximum of 16 bits cmp cx,16 jg .DEBUG_2 jmp .BIN .DEC: ; decimal - read a maximum of 5 decimal digits xor ebx,ebx cmp [esi],byte 0 je .CHECK cmp [esi],byte '0' jl .DEBUG_4 cmp [esi],byte '9' jg .DEBUG_4 ; multiply EDX by 10 mov ebx,edx shl ebx,3 shl edx,1 add edx,ebx ; add the new digit to EDX xor ebx,ebx mov bl,[esi] sub bl,'0' add edx,ebx .NEXT_D: inc esi inc cx ; read a maximum of 5 decimal digits cmp cx,5 jg .DEBUG_2 jmp .DEC .CHECK: cmp edx,65536 jb .DONE ; decimal number is greater than a 2 byte value mov [Debug_Code],word 19 jmp .ERROR .DEBUG_1: ; invalid char in hex number mov [Debug_Code],word 20 jmp .ERROR .DEBUG_2: ; too many digits mov [Debug_Code],word 21 jmp .ERROR .DEBUG_3: ; invalid char in binary number mov [Debug_Code],word 22 jmp .ERROR .DEBUG_4: ; invalid char in decimal number mov [Debug_Code],word 23 .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Read_Hex uses esi ebx ; read a hex number from bfOperand - for the HEX pseudo-op ; max size = 4 bytes = 8 hex digits ; return in EDX ; called by proc Process_Labels_PsOps_1 and proc Process_Labels_PsOps_2 xor edx,edx lea esi,[bfOperand] xor ecx,ecx .READ: ; read a pair of hex digits ; BH = the high nibble mov bh,[esi] cmp bh,0 je .1 ; BL = the low nibble inc esi mov bl,[esi] cmp bl,0 je .1 .D1: cmp bh,'0' jl .DEBUG_1 cmp bh,'9' jg .AF_D1 sub bh,'0' jmp .D2 .AF_D1: cmp bh,'A' jl .DEBUG_1 cmp bh,'F' jg .DEBUG_1 sub bh,'A' add bh,10 .D2: cmp bl,'0' jl .DEBUG_1 cmp bl,'9' jg .AF_D2 sub bl,'0' jmp .CALC .AF_D2: cmp bl,'A' jl .DEBUG_1 cmp bl,'F' jg .DEBUG_1 sub bl,'A' add bl,10 .CALC: shl bh,4 or bl,bh ; the byte is now in BL - add to EDX shl edx,8 mov dl,bl .NEXT: inc esi inc cx ; read a maximum of 8 hex digits (4 bytes) cmp cx,4 jg .DEBUG_2 jmp .READ .DEBUG_1: ; invalid char mov [Debug_Code],word 24 jmp .ERROR .DEBUG_2: ; too many digits mov [Debug_Code],word 25 .ERROR: mov eax,0xffffffff jmp .DONE ; put EDX into the correct byte order .1: cmp cx,1 jle .DONE .2: cmp cx,2 jg .3 bswap edx shr edx,16 jmp .DONE .3: cmp cx,3 jg .4 bswap edx shr edx,8 jmp .DONE .4: bswap edx .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Get_Hex_Value uses ecx ; read up to 4 hex digits from ESI ; ESI is set outside of this proc ; return result in EAX - a 1 or 2 byte value ; called by proc Calc_Operand_Value xor eax,eax xor ecx,ecx ; first char from ESI must be a valid hex digit cmp [esi],byte '0' jl .DEBUG_1 cmp [esi],byte '9' jle .ADD_09 cmp [esi],byte 'A' jl .DEBUG_1 cmp [esi],byte 'F' jle .ADD_AF jmp .DEBUG_1 .NEXT: ; get the next hex digit ; stop reading digits when a null, plus, minus, comma or ) is found inc esi cmp [esi],byte 0 je .CALC cmp [esi],byte '+' je .CALC cmp [esi],byte '-' je .CALC cmp [esi],byte ',' je .CALC cmp [esi],byte ')' je .CALC cmp [esi],byte '0' jl .DEBUG_1 cmp [esi],byte '9' jle .ADD_09 cmp [esi],byte 'A' jl .DEBUG_1 cmp [esi],byte 'F' jle .ADD_AF jmp .DEBUG_1 .ADD_09: ; add the digit to EAX (0-9) shl eax,8 mov al,[esi] sub al,'0' inc cx cmp cx,4 jg .DEBUG_2 jmp .NEXT .ADD_AF: ; add the digit to EAX (A-F) shl eax,8 mov al,[esi] sub al,'A' add al,10 inc cx cmp cx,4 jg .DEBUG_2 jmp .NEXT .CALC: ; convert to a 2 byte value shl ah,4 or al,ah mov ecx,eax shr ecx,16 shl ch,4 or cl,ch mov ah,cl and eax,0xffff jmp .DONE .DEBUG_1: ; invalid char mov [Debug_Code],word 26 jmp .ERROR .DEBUG_2: ; too many digits (max = 4) mov [Debug_Code],word 27 .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Get_Dec_Value uses ebx ecx edx ; read up to 5 decimal digits from ESI ; value must be less than or equal to 65536 ; ESI is set outside of this proc ; return result in EAX - a 1 or 2 byte value ; called by proc Calc_Operand_Value xor eax,eax xor edx,edx .DIGIT_1: ; the first char from ESI must be a decimal digit cmp [esi],byte '0' jl .DEBUG_1 cmp [esi],byte '9' jg .DEBUG_1 mov dl,[esi] sub dl,'0' mov eax,edx mov ecx,1 .NEXT: ; get the next decimal digit ; stop reading digits when a null, plus, minus, comma or ) is found inc esi cmp [esi],byte 0 je .CHECK cmp [esi],byte '+' je .CHECK cmp [esi],byte '-' je .CHECK cmp [esi],byte ',' je .CHECK cmp [esi],byte ')' je .CHECK cmp [esi],byte '0' jl .DEBUG_1 cmp [esi],byte '9' jg .DEBUG_1 .ADD_D: ; add the digit to EAX mov dl,[esi] sub dl,'0' ; multiply EAX by 10 mov ebx,eax shl ebx,3 shl eax,1 add eax,ebx ; add the new digit add eax,edx ; read up to 5 digits inc cl cmp cl,5 jg .DEBUG_2 jmp .NEXT .CHECK: ; is the decimal number 2 bytes or less ? cmp eax,65535 ja .DEBUG_3 jmp .DONE .DEBUG_1: ; invalid char mov [Debug_Code],word 28 jmp .ERROR .DEBUG_2: ; too many digits mov [Debug_Code],word 29 jmp .ERROR .DEBUG_3: ; result is greater than 2 bytes mov [Debug_Code],word 30 .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Get_Bin_Value uses ebx ; read up to 16 binary digits from ESI ; ESI is set outside of this proc ; return result in EAX - a 1 or 2 byte value ; called by proc Calc_Operand_Value xor eax,eax xor ecx,ecx ; first char from ESI must be a valid binary digit cmp [esi],byte '0' jl .DEBUG_1 cmp [esi],byte '1' jle .ADD_BIN jmp .DEBUG_1 .NEXT: ; get the next binary digit ; stop reading digits when a null, plus, minus, comma or ) is found inc esi cmp [esi],byte 0 je .DONE cmp [esi],byte '+' je .DONE cmp [esi],byte '-' je .DONE cmp [esi],byte ',' je .DONE cmp [esi],byte ')' je .DONE cmp [esi],byte '0' jl .DEBUG_1 cmp [esi],byte '1' jle .ADD_BIN ; an invalid char has been found: jmp .DEBUG_1 .ADD_BIN: ; add the digit to EAX shl eax,1 mov bl,[esi] sub bl,'0' or al,bl inc cx cmp cx,16 jg .DEBUG_2 jmp .NEXT .DEBUG_1: ; invalid char mov [Debug_Code],word 39 jmp .ERROR .DEBUG_2: ; too many digits (max = 16) mov [Debug_Code],word 40 .ERROR: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Store_Hex uses edi ebx ; store the bytes passed in EDX in memory - up to 4 bytes ; CL gives the number of bytes to store lea edi,[Main_Memory] xor ebx,ebx mov bx,[Location_Counter] ; byte 1 jcxz .DONE mov [edi+ebx],dl inc word [Location_Counter] dec cx ; byte 2 jcxz .DONE inc bx shr edx,8 mov [edi+ebx],dl inc word [Location_Counter] dec cx ; byte 3 jcxz .DONE inc bx shr edx,8 mov [edi+ebx],dl inc word [Location_Counter] dec cx ; byte 4 jcxz .DONE inc bx shr edx,8 mov [edi+ebx],dl inc word [Location_Counter] .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Char_To_Upper ; if the char in AL is lower case - convert to upper case cmp al,97 jl .DONE cmp al,122 jg .DONE sub al,32 .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Increment_Symbol_Pointer ; increment the symbol pointer xor eax,eax ; increment by adding 16 bytes add [pSymbol_Table],16 lea edx,[Main_Memory] add edx,65536 cmp edx,[pSymbol_Table] jg .DONE ; error - the symbol pointer points past the end of the 6502's memory mov eax,0xffffffff mov [Debug_Code],word 11 .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Reset_Symbol_Pointer ; reset the symbol table pointer ; symbol table = pages 252, 253, 254, 255 lea edx,[Main_Memory] ; symbol table starts on page 252 add edx,64512 mov [pSymbol_Table],edx ret endp ; ------------------------------------------------------------------------------------- proc Print_Symbol_Table uses ebx ; print the symbol table to bfDisplay lea edi,[bfDisplay] lea esi,[Main_Memory] ; symbol table starts on page 252 add esi,64512 mov edx,64512 .ROW: ; exit if the table entry is NULL cmp [esi],byte 0 je .DONE ; print the address of the table entry (in DX) mov al,dh stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov al,dl stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],dword 0x20203A20 add edi,4 mov [edi],word 0x2020 add edi,2 xor ecx,ecx .PRINT: ; print the symbol - up to 14 chars mov al,[esi] cmp al,0 jne .SKIP mov al,32 .SKIP: mov [edi],al inc esi inc edi inc cx cmp cx,14 jl .PRINT mov [edi],dword 0x20202020 add edi,4 mov [edi],byte '$' inc edi ; print the address pointed to by the symbol inc esi stdcall Byte_To_Ascii dec esi stdcall Byte_To_Ascii add esi,2 PRINT_CRLF add edx,16 jmp .ROW .DONE: mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Print_Compile_Error ; if the compile fails, print an error message lea edi,[bfOutput] mov [edi],dword "Comp" add edi,4 mov [edi],dword "ile " add edi,4 mov [edi],dword "Erro" add edi,4 mov [edi],dword "r in" add edi,4 mov [edi],dword " the" add edi,4 mov [edi],dword " lin" add edi,4 mov [edi],dword "e: " add edi,4 mov [edi],dword 0x0A0D0A0D add edi,4 lea esi,[bfCurrentLine] ; print the current line .COPY: mov al,[esi] cmp al,0 je .ERR mov [edi],al inc esi inc edi jmp .COPY .ERR: ; check the debug code to determine which error message to print mov [edi],dword 0x0A0D0A0D add edi,4 mov al,byte [Debug_Code] cmp al,1 je .ERR_1 cmp al,2 je .ERR_2 cmp al,3 je .ERR_3 cmp al,4 je .ERR_4 cmp al,5 je .ERR_5 cmp al,6 je .ERR_6 cmp al,7 je .ERR_7 cmp al,8 je .ERR_8 cmp al,9 je .ERR_9 cmp al,10 je .ERR_10 cmp al,11 je .ERR_11 cmp al,12 je .ERR_12 cmp al,13 je .ERR_13 cmp al,14 je .ERR_14 cmp al,15 je .ERR_15 cmp al,16 je .ERR_16 cmp al,17 je .ERR_17 cmp al,18 je .ERR_18 cmp al,19 je .ERR_19 cmp al,20 je .ERR_20 cmp al,21 je .ERR_21 cmp al,22 je .ERR_22 cmp al,23 je .ERR_23 cmp al,24 je .ERR_24 cmp al,25 je .ERR_25 cmp al,26 je .ERR_26 cmp al,27 je .ERR_27 cmp al,28 je .ERR_28 cmp al,29 je .ERR_29 cmp al,30 je .ERR_30 cmp al,31 je .ERR_31 cmp al,32 je .ERR_32 cmp al,33 je .ERR_33 cmp al,34 je .ERR_34 cmp al,35 je .ERR_35 cmp al,36 je .ERR_36 cmp al,37 je .ERR_37 cmp al,39 je .ERR_39 cmp al,40 je .ERR_40 cmp al,41 je .ERR_41 cmp al,43 je .ERR_43 .ERR_0: lea esi,[szErrMessage_0] jmp .PRINT .ERR_1: lea esi,[szErrMessage_1] jmp .PRINT .ERR_2: lea esi,[szErrMessage_2] jmp .PRINT .ERR_3: lea esi,[szErrMessage_3] jmp .PRINT .ERR_4: lea esi,[szErrMessage_4] jmp .PRINT .ERR_5: lea esi,[szErrMessage_5] jmp .PRINT .ERR_6: lea esi,[szErrMessage_6] jmp .PRINT .ERR_7: lea esi,[szErrMessage_7] jmp .PRINT .ERR_8: lea esi,[szErrMessage_8] jmp .PRINT .ERR_9: lea esi,[szErrMessage_9] jmp .PRINT .ERR_10: lea esi,[szErrMessage_10] jmp .PRINT .ERR_11: lea esi,[szErrMessage_11] jmp .PRINT .ERR_12: lea esi,[szErrMessage_12] jmp .PRINT .ERR_13: lea esi,[szErrMessage_13] jmp .PRINT .ERR_14: lea esi,[szErrMessage_14] jmp .PRINT .ERR_15: lea esi,[szErrMessage_15] jmp .PRINT .ERR_16: lea esi,[szErrMessage_16] jmp .PRINT .ERR_17: lea esi,[szErrMessage_17] jmp .PRINT .ERR_18: lea esi,[szErrMessage_18] jmp .PRINT .ERR_19: lea esi,[szErrMessage_19] jmp .PRINT .ERR_20: lea esi,[szErrMessage_20] jmp .PRINT .ERR_21: lea esi,[szErrMessage_21] jmp .PRINT .ERR_22: lea esi,[szErrMessage_22] jmp .PRINT .ERR_23: lea esi,[szErrMessage_23] jmp .PRINT .ERR_24: lea esi,[szErrMessage_24] jmp .PRINT .ERR_25: lea esi,[szErrMessage_25] jmp .PRINT .ERR_26: lea esi,[szErrMessage_26] jmp .PRINT .ERR_27: lea esi,[szErrMessage_27] jmp .PRINT .ERR_28: lea esi,[szErrMessage_28] jmp .PRINT .ERR_29: lea esi,[szErrMessage_29] jmp .PRINT .ERR_30: lea esi,[szErrMessage_30] jmp .PRINT .ERR_31: lea esi,[szErrMessage_31] jmp .PRINT .ERR_32: lea esi,[szErrMessage_32] jmp .PRINT .ERR_33: lea esi,[szErrMessage_33] jmp .PRINT .ERR_34: lea esi,[szErrMessage_34] jmp .PRINT .ERR_35: lea esi,[szErrMessage_35] jmp .PRINT .ERR_36: lea esi,[szErrMessage_36] jmp .PRINT .ERR_37: lea esi,[szErrMessage_37] jmp .PRINT .ERR_39: lea esi,[szErrMessage_39] jmp .PRINT .ERR_40: lea esi,[szErrMessage_40] jmp .PRINT .ERR_41: lea esi,[szErrMessage_41] jmp .PRINT .ERR_43: lea esi,[szErrMessage_43] .PRINT: ; print the error message mov al,[esi] cmp al,0 je .DONE mov [edi],al inc esi inc edi jmp .PRINT .DONE: mov [edi],dword 0x0A0D0A0D add edi,4 mov [edi],dword "Debu" add edi,4 mov [edi],dword "g Co" add edi,4 mov [edi],dword "de: " add edi,4 mov dl,byte [Debug_Code] stdcall Byte_To_Decimal mov [edi],ah inc edi mov [edi],al inc edi mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Print_Exe_Error ; if an instruction fails to execute, print an error message lea edi,[bfDisplay] lea esi,[szErrMessage_38] .PRINT: ; print the error message mov al,[esi] cmp al,0 je .DONE mov [edi],al inc esi inc edi jmp .PRINT .DONE: mov [edi],dword 0x0A0D0A0D add edi,4 mov [edi],dword "Prog" add edi,4 mov [edi],dword "ram " add edi,4 mov [edi],dword "Coun" add edi,4 mov [edi],dword "ter:" add edi,4 mov [edi],byte 32 inc edi mov ax,word [Exe_Info] shr ax,8 stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov ax,word [Exe_Info] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],dword 0x0A0D0A0D add edi,4 mov [edi],dword "Inst" add edi,4 mov [edi],dword "ruct" add edi,4 mov [edi],dword "ion " add edi,4 mov [edi],dword "Byte" add edi,4 mov [edi],word ": " add edi,2 mov al,byte [Debug_Code] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Reset_Output uses edi ; the compile result is written to bfOutput: ; the value of the location counter, the bytes that were assembled and the input line ; pOutput points to the current position within bfOutput - reset pOutput mov dword [pOutput],0 lea edi,[bfOutput] mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Write_LC_To_Output uses edi ecx edx ; before assembling the next line, write the value of the location counter to output lea edi,[bfOutput] mov edx,[pOutput] cmp edx,32600 jge .ERROR mov cx,word [Location_Counter] ; write the location counter (in CX) mov al,ch stdcall Byte_To_Hex mov [edi+edx],ah inc edx mov [edi+edx],al inc edx mov al,cl stdcall Byte_To_Hex mov [edi+edx],ah inc edx mov [edi+edx],al inc edx mov [edi+edx],byte 9 inc edx ; null terminate mov [edi+edx],byte 0 jmp .DONE .ERROR: mov [Debug_Code],word 43 mov eax,0xffffffff .DONE: ; update pOutput mov dword [pOutput],edx ret endp ; ------------------------------------------------------------------------------------- proc Write_Asm_To_Output uses esi edi ebx edx ; after the current line has been assembled, write the result to bfOutput: ; the assembled bytes ; the text of each field in the current line locals nBytes db 0 endl lea edi,[bfOutput] mov edx,[pOutput] cmp edx,32600 jge .ERROR ; write the bytes that were assembled mov ebx,[Asm_Bytes] bswap ebx mov [nBytes],bl ; if there was just a label on the line: cmp byte [nBytes],0 je .PAD_0 bswap ebx ; write the op code byte mov al,bl stdcall Byte_To_Hex mov [edi+edx],ah inc edx mov [edi+edx],al inc edx mov [edi+edx],byte 32 cmp byte [nBytes],1 je .PAD_1 inc edx ; write the first data byte (if any) shr ebx,8 mov al,bl stdcall Byte_To_Hex mov [edi+edx],ah inc edx mov [edi+edx],al inc edx mov [edi+edx],byte 32 cmp byte [nBytes],2 je .PAD_2 inc edx ; write the second data byte (if any) mov al,bh stdcall Byte_To_Hex mov [edi+edx],ah inc edx mov [edi+edx],al inc edx jmp .TEXT .PAD_0: mov [edi+edx],word "--" add edx,2 .PAD_1: mov [edi+edx],byte 32 inc edx mov [edi+edx],word "--" add edx,2 .PAD_2: mov [edi+edx],byte 32 inc edx mov [edi+edx],word "--" add edx,2 .TEXT: mov [edi+edx],byte 9 inc edx ; write the bfLabel, bfMnemonic and bfOperand fields lea esi,[bfLabel] .COPY_L: mov al,[esi] cmp al,0 je .COPY_M mov [edi+edx],al inc edx inc esi jmp .COPY_L .COPY_M: mov [edi+edx],byte 32 inc edx lea esi,[bfMnemonic] ; 1st letter mov al,[esi] cmp al,0 je .NEXT mov [edi+edx],al inc edx ; 2nd letter mov al,[esi+1] cmp al,0 je .NEXT mov [edi+edx],al inc edx ; 3rd letter mov al,[esi+2] cmp al,0 je .NEXT mov [edi+edx],al inc edx .NEXT: mov [edi+edx],byte 32 inc edx lea esi,[bfOperand] .COPY_OP: mov al,[esi] cmp al,0 je .LAST mov [edi+edx],al inc edx inc esi jmp .COPY_OP .LAST: mov [edi+edx],byte 13 inc edx mov [edi+edx],byte 10 inc edx ; null terminate mov [edi+edx],byte 0 jmp .DONE .ERROR: mov [Debug_Code],word 43 mov eax,0xffffffff .DONE: ; update pOutput mov dword [pOutput],edx ret endp ; ------------------------------------------------------------------------------------- proc Write_Line_To_Output uses esi edi ebx edx ; when the current line contains an ADR, DBY, BYT, HBY, EQU, EPZ, DFS, HEX, ORG pseudo-op ; call this function (in pass 2) ; to write the text of each field in the current line to bfOutput lea edi,[bfOutput] mov edx,[pOutput] cmp edx,32600 jge .ERROR ; the pseudo-ops emit no assembly code bytes, so these fields will be blank mov [edi+edx],word "--" add edx,2 mov [edi+edx],byte 32 inc edx mov [edi+edx],word "--" add edx,2 mov [edi+edx],byte 32 inc edx mov [edi+edx],word "--" add edx,2 mov [edi+edx],byte 32 inc edx .TEXT: mov [edi+edx],byte 9 inc edx ; write the bfLabel, bfMnemonic and bfOperand fields lea esi,[bfLabel] .COPY_L: mov al,[esi] cmp al,0 je .COPY_M mov [edi+edx],al inc edx inc esi jmp .COPY_L .COPY_M: mov [edi+edx],byte 32 inc edx lea esi,[bfMnemonic] ; 1st letter mov al,[esi] cmp al,0 je .NEXT mov [edi+edx],al inc edx ; 2nd letter mov al,[esi+1] cmp al,0 je .NEXT mov [edi+edx],al inc edx ; 3rd letter mov al,[esi+2] cmp al,0 je .NEXT mov [edi+edx],al inc edx .NEXT: mov [edi+edx],byte 32 inc edx lea esi,[bfOperand] .COPY_OP: mov al,[esi] cmp al,0 je .LAST mov [edi+edx],al inc edx inc esi jmp .COPY_OP .LAST: mov [edi+edx],byte 13 inc edx mov [edi+edx],byte 10 inc edx ; null terminate mov [edi+edx],byte 0 jmp .DONE .ERROR: mov [Debug_Code],word 43 mov eax,0xffffffff .DONE: ; update pOutput mov dword [pOutput],edx ret endp ; ------------------------------------------------------------------------------------- proc Print_Last_Exe_Info uses esi edi ; print the details about the last instruction that was executed ; from the Exe_Info structure: ; ================================================ ; bytes 0,1 = Program Counter ; bytes 2,3,4 = Mnemonic ; byte 5 = addressing mode ; bytes 6,7 = target address ; bytes 8,9,A,B = dword at target address ; ================================================ ; addressing modes (byte 5): ; 0 = accumulator ; 1 = implied ; 2 = relative ; 3 = immediate ; 4 = absolute ; 5 = zero page ; 6 = a,x ; 7 = a,y ; 8 = zp,x ; 9 = zp,y ; 10 = (zp,x) ; 11 = (zp),y ; 12 = (a) ; ================================================ lea esi,[Exe_Info] lea edi,[bfDisplay] mov [edi],dword "Last" add edi,4 mov [edi],dword " Ins" add edi,4 mov [edi],dword "truc" add edi,4 mov [edi],dword "tion" add edi,4 mov [edi],dword " Exe" add edi,4 mov [edi],dword "cute" add edi,4 mov [edi],dword "d = " add edi,4 ; print the program counter mov al,[esi+1] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov al,[esi] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],byte 32 inc edi ; print the mnemonic mov al,[esi+2] mov [edi],al inc edi mov al,[esi+3] mov [edi],al inc edi mov al,[esi+4] mov [edi],al inc edi PRINT_CRLF PRINT_CRLF ; print the addressing mode mov [edi],dword "Addr" add edi,4 mov [edi],dword "essi" add edi,4 mov [edi],dword "ng M" add edi,4 mov [edi],dword "ode " add edi,4 mov [edi],dword "= " add edi,2 ; get the addressing mode mov al,[esi+5] cmp al,0 je .ACC cmp al,1 je .IMP cmp al,2 je .REL cmp al,3 je .IMM cmp al,4 je .ABS cmp al,5 je .ZP cmp al,6 je .AX cmp al,7 je .AY cmp al,8 je .ZPX cmp al,9 je .ZPY cmp al,10 je .ZPIX cmp al,11 je .ZPIY cmp al,12 je .IND_A jmp .UN .ACC: mov [edi],dword "Accu" add edi,4 mov [edi],dword "mula" add edi,4 mov [edi],dword "tor " add edi,4 jmp .DONE .IMP: mov [edi],dword "Impl" add edi,4 mov [edi],dword "ied " add edi,4 jmp .DONE .REL: mov [edi],dword "Rela" add edi,4 mov [edi],dword "tive" add edi,4 jmp .DONE .IMM: mov [edi],dword "Imme" add edi,4 mov [edi],dword "diat" add edi,4 mov [edi],word "e " add edi,2 PRINT_CRLF PRINT_CRLF mov [edi],dword "Byte" add edi,4 mov [edi],word " =" add edi,2 mov [edi],byte 32 inc edi mov al,[esi+8] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi jmp .DONE .ABS: mov [edi],dword "Abso" add edi,4 mov [edi],dword "lute" add edi,4 jmp .TA .ZP: mov [edi],dword "Zero" add edi,4 mov [edi],dword " Pag" add edi,4 mov [edi],word "e " add edi,2 jmp .TA .AX: mov [edi],dword "a,x " add edi,4 jmp .TA .AY: mov [edi],dword "a,y " add edi,4 jmp .TA .ZPX: mov [edi],dword "zp,x" add edi,4 jmp .TA .ZPY: mov [edi],dword "zp,y" add edi,4 jmp .TA .ZPIX: mov [edi],dword "(zp," add edi,4 mov [edi],word "x)" add edi,2 jmp .TA .ZPIY: mov [edi],dword "(zp)" add edi,4 mov [edi],word ",y" add edi,2 jmp .TA .IND_A: mov [edi],dword "(a) " add edi,4 jmp .TA .UN: mov [edi],dword "Unkn" add edi,4 mov [edi],dword "own " add edi,4 jmp .DONE .TA: PRINT_CRLF PRINT_CRLF mov [edi],dword "Targ" add edi,4 mov [edi],dword "et A" add edi,4 mov [edi],dword "ddre" add edi,4 mov [edi],dword "ss =" add edi,4 mov [edi],byte 32 inc edi mov al,[esi+7] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov al,[esi+6] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi PRINT_CRLF PRINT_CRLF .DW: ; print the 4 bytes in memory starting from the target address stdcall Get_Exe_Info_89 mov [edi],dword "Byte" add edi,4 mov [edi],dword "s(Ad" add edi,4 mov [edi],dword "dres" add edi,4 mov [edi],dword "s) =" add edi,4 mov [edi],byte 32 inc edi mov al,[esi+8] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],byte 32 inc edi mov al,[esi+9] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],byte 32 inc edi mov al,[esi+10] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],byte 32 inc edi mov al,[esi+11] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi .DONE: mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Get_Exe_Info_89 uses esi ; get the dword at the target address lea esi,[Main_Memory] xor edx,edx mov dx,word [Exe_Info_67] mov edx,[esi+edx] mov dword [Exe_Info_89],edx ret endp ; ------------------------------------------------------------------------------------- proc Reset_Exe_Info uses edi ; clear the Exe_Info data structure lea edi,[Exe_Info] mov [edi],dword 0 mov [edi+4],dword 0 mov [edi+8],dword 0 ret endp ; ------------------------------------------------------------------------------------- proc Add_To_Watch ; add a symbol or address to the watch ; input formats: ; (1) $hhhh,nbytes ; (2) Symbol,nbytes locals addr dw 0 endl lea esi,[bfDisplay] ; convert all letters to uppercase .UP: mov al,[esi] stdcall Char_To_Upper mov [esi],al inc esi cmp al,0 jne .UP lea esi,[bfDisplay] ; read the input cmp [esi],byte '$' je .ADDR cmp [esi],byte 'A' jl .ERROR cmp [esi],byte 'Z' jle .SYMB .ERROR: mov eax,0xffffffff jmp .DONE .ADDR: ; read a hexadecimal address inc esi stdcall Get_Hex_Value cmp eax,0xffffffff je .DONE mov word [addr],ax jmp .N_BYTES .SYMB: ; read a symbol lea edi,[bfSymbol] .COPY: mov al,[esi] cmp al,',' je .NULL_T cmp al,0 je .ERROR mov [edi],al inc esi inc edi jmp .COPY .NULL_T: mov [edi],byte 0 stdcall Find_Symbol cmp eax,0xffffffff je .DONE mov word [addr],ax .N_BYTES: ; read the number of bytes inc esi stdcall Get_Dec_Value cmp eax,0xffffffff je .DONE cmp ax,256 jle .NEXT mov ax,256 .NEXT: mov dx,ax shl edx,16 mov dx,word [addr] ; add to the watch array - passed in EDX stdcall Add_To_Watch_Arr .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Add_To_Watch_Arr uses edi ecx ; add an entry to the watch array ; data passed in EDX: ; bytes 0,1 = address ; bytes 2,3 = number of bytes to display ; Watch_Arr has room for 12 entries ; W_Arr_Index gives the index (0-11) ; W_Arr_Index wraps back to zero once the watch array is full lea edi,[Watch_Arr] xor ecx,ecx mov cl,[W_Arr_Index] shl ecx,2 add edi,ecx mov [edi],edx inc byte [W_Arr_Index] cmp byte [W_Arr_Index],12 jl .DONE mov byte [W_Arr_Index],0 .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Reset_Watch_Arr ; reset the watch array mov byte [W_Arr_Index],0 lea edi,[Watch_Arr] xor ecx,ecx .CLEAR: mov [edi],dword 0 add edi,4 inc cx cmp cx,12 jl .CLEAR ret endp ; ------------------------------------------------------------------------------------- proc Find_Symbol uses esi edi ecx edx ; find the current symbol in the symbol table ; get the address of the entry within the main memory ; return the result in AX lea esi,[bfSymbol] lea edi,[Main_Memory] mov edx,64512 add edi,edx ; check if there are any symbols cmp [edi],byte 0 je .NO_MATCH xor ecx,ecx .TEST: ; test bfSymbol against the current entry in the symbol table mov al,[esi+ecx] cmp al,[edi+ecx] jne .NEXT cmp al,0 je .MATCH inc cx cmp cx,14 jl .TEST .NEXT: xor ecx,ecx add edi,16 add edx,16 cmp [edi],byte 0 je .NO_MATCH jmp .TEST .MATCH: ; copy the result to EAX mov eax,edx jmp .DONE .NO_MATCH: mov eax,0xffffffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Print_Watch_Error ; bad input - could not add to the watch ; print an error message lea edi,[bfDisplay] lea esi,[szErrMessage_42] .PRINT: mov al,[esi] mov [edi],al cmp al,0 je .DONE inc esi inc edi jmp .PRINT .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Print_Watch ; print the watch array lea esi,[Watch_Arr] lea edi,[bfDisplay] locals index db 0 count db 0 endl .W_ARR: ; read the next entry - exit if zero mov edx,[esi] cmp edx,0 je .DONE cmp dx,64512 jb .ADDR .SYMB: ; DX points to an entry in the symbol table ; get the symbol lea ebx,[Main_Memory] xor ecx,ecx mov cx,dx ; set EBX to point to the table entry add ebx,ecx .COPY: ; print out the symbol mov al,[ebx] cmp al,0 je .NEXT mov [edi],al inc edi inc ebx jmp .COPY .NEXT: mov [edi],byte ":" inc edi PRINT_CRLF PRINT_CRLF ; adjust DX so that it points to the memory address pointed to by the symbol lea ebx,[Main_Memory] xor ecx,ecx mov cx,dx add ebx,ecx ; the last 2 bytes of the 16 byte table entry holds the address add bx,14 ; adjust DX mov dx,[ebx] jmp .BYTES .ADDR: ; print out the address mov al,dh stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov al,dl stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],byte ":" inc edi PRINT_CRLF PRINT_CRLF .BYTES: ; print the bytes at the memory address lea ebx,[Main_Memory] xor ecx,ecx mov cx,dx add ebx,ecx mov ecx,edx shr ecx,16 mov byte [count],0 .LOOP: mov al,[ebx] stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],byte 32 inc edi inc ebx inc byte [count] cmp byte [count],16 jl .SKIP ; print a CRLF for every 16 bytes printed mov byte [count],0 PRINT_CRLF .SKIP: dec cx cmp cx,0 jg .LOOP PRINT_CRLF PRINT_CRLF ; if the index reaches 12 the entire watch array has been printed inc byte [index] cmp byte [index],12 jge .DONE add esi,4 ; jump to read the next entry jmp .W_ARR .DONE: mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Init_ASC ; initialise the message that is displayed in the ASCII input/output window lea edi,[bfDisplay] mov [edi],dword 0x65746E45 add edi,4 mov [edi],dword 0x6E612072 add edi,4 mov [edi],dword 0x63734120 add edi,4 mov [edi],dword 0x74206969 add edi,4 mov [edi],dword 0x20747865 add edi,4 mov [edi],dword 0x69727473 add edi,4 mov [edi],dword 0x6820676E add edi,4 mov [edi],dword 0x20657265 add edi,4 mov [edi],dword 0x20646E61 add edi,4 mov [edi],dword 0x73657270 add edi,4 mov [edi],dword 0x4C5B2073 add edi,4 mov [edi],dword 0x2064616F add edi,4 mov [edi],dword 0x49435341 add edi,4 mov [edi],dword 0x5D49 add edi,2 mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc Load_ASC ; read an ascii string from the ASCII input/output edit control ; read a maximum of 1024 chars ; load into main memory: pages 248, 249, 250, 251 ; page 248 : byte offset = 63488 lea esi,[bfDisplay] lea edi,[Main_Memory] add edi,63488 xor ecx,ecx .LOAD: ; load up to 1024 bytes mov al,[esi] cmp al,0 je .CLEAR ; filter out CRLF cmp al,13 je .SKIP cmp al,10 je .SKIP mov [edi],al inc edi inc cx .SKIP: inc esi cmp cx,1024 jb .LOAD .CLEAR: ; clear any previous data from the rest of the buffer mov [edi],byte 0 inc edi inc cx cmp cx,1024 jb .CLEAR .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Print_ASC ; print the contents of pages 248, 249, 250, 251 to bfDisplay locals count_1 db 0 count_2 db 0 endl lea esi,[Main_Memory] add esi,63488 lea edi,[bfDisplay] xor ecx,ecx mov edx,63488 .ROW: ; print the address of the row (in DX) mov al,dh stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov al,dl stdcall Byte_To_Hex mov [edi],ah inc edi mov [edi],al inc edi mov [edi],dword 0x20203A20 add edi,4 .PRINT: ; print a char mov al,[esi] ; printable chars have ascii values from 32 to 126 ; replace non-printing chars with a space cmp al,31 ja .SKIP .SPC: mov al,32 .SKIP: cmp al,127 je .SPC ; write the char to the output buffer mov [edi],al inc esi inc edi inc cx cmp cx,1024 jge .DONE ; print a CRLF after every 32 chars inc byte [count_1] cmp byte [count_1],32 jl .PRINT mov byte [count_1],0 add edx,32 PRINT_CRLF ; print an extra CRLF after every 8 rows (1 page of memory = 256 bytes) inc byte [count_2] cmp byte [count_2],8 jl .NEXT mov byte [count_2],0 PRINT_CRLF .NEXT: jmp .ROW .DONE: mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- section '.idata' import data readable writeable library kernel,'KERNEL32.DLL',\ user,'USER32.DLL' import kernel,\ GetModuleHandle,'GetModuleHandleA',\ ExitProcess,'ExitProcess' import user,\ DialogBoxParam,'DialogBoxParamA',\ GetDlgItem,'GetDlgItem',\ SetDlgItemText,'SetDlgItemTextA',\ GetDlgItemText,'GetDlgItemTextA',\ SendMessage,'SendMessageA',\ EndDialog,'EndDialog' ; ------------------------------------------------------------------------------------- section '.data' readable writeable bfCurrentLine rb 128 bfLabel rb 16 bfMnemonic rb 4 bfOperand rb 112 bfExpression rb 32 bfSymbol rb 16 Operand_Data rb 4 Exe_Info rb 2 Exe_Info_2345 rb 4 Exe_Info_67 rb 2 Exe_Info_89 rb 4 pSymbol_Table dd 0 Watch_Arr rb 48 W_Arr_Index db 0 Watch_On db 0 Accumulator db 0 Index_Reg_X db 0 Index_Reg_Y db 0 Stack_Pointer db 0 NV_ZC db 0 Next_Dlg_ID db 0 Program_Counter dw 0x200 Location_Counter dw 0x200 Debug_Code dw 0 Asm_Bytes dd 0 Main_Memory rb 65536 szInputText db "Enter code here and press [Compile Assembly]:",0 cbString rb 32 hCBX dd 0 szErrMessage_0 db "Error: unknown compile error.",0 szErrMessage_1 db "Error: length of input line must be less than 128 chars.",0 szErrMessage_2 db "Error: extra chars in the line.",0 szErrMessage_3 db "Error: length of label must be 14 chars or less.",0 szErrMessage_4 db "Error: invalid chars in the mnemonic field.",0 szErrMessage_5 db "Error: length of operand field must be less than 112 chars.",0 szErrMessage_6 db "Error: too many chars in the mnemonic field.",0 szErrMessage_7 db "Error: EQU, EPZ or DFS ops require a label.",0 szErrMessage_8 db "Error: operand for EPZ must evaluate to a 1 byte value.",0 szErrMessage_9 db "Error: label matches an existing entry in the symbol table.",0 szErrMessage_10 db "Error: char after plus or minus sign is invalid.",0 szErrMessage_11 db "Error: symbol table is full.",0 szErrMessage_12 db "Error: invalid char in the operand.",0 szErrMessage_13 db "Error: hex number contains an invalid char.",0 szErrMessage_14 db "Error: decimal number contains an invalid char.",0 szErrMessage_15 db "Error: binary number contains an invalid char.",0 szErrMessage_16 db "Error: label contains invalid chars.",0 szErrMessage_17 db "Error: unknown mnemonic.",0 szErrMessage_18 db "Error: invalid mnemonic and operand size combination.",0 szErrMessage_19 db "Error: decimal number in operand must be less than 65536.",0 szErrMessage_20 db "Error: invalid chars in hex number.",0 szErrMessage_21 db "Error: too many digits in number.",0 szErrMessage_22 db "Error: invalid chars in binary number.",0 szErrMessage_23 db "Error: invalid chars in decimal number.",0 szErrMessage_24 db "Error: invalid chars in hex number.",0 szErrMessage_25 db "Error: HEX op - max length of operand is 8 hex digits.",0 szErrMessage_26 db "Error: invalid chars in hex number.",0 szErrMessage_27 db "Error: max length of hex number is 4 digits.",0 szErrMessage_28 db "Error: invalid chars in decimal number.",0 szErrMessage_29 db "Error: max length of decimal number is 5 digits.",0 szErrMessage_30 db "Error: decimal number in operand must be less than 65536.",0 szErrMessage_31 db "Error: could not detect addressing mode of the operand.",0 szErrMessage_32 db "Error: operand contains invalid chars.",0 szErrMessage_33 db "Error: could not determine value of symbol in the operand.",0 szErrMessage_34 db "Error: could not find symbol in the symbol table.",0 szErrMessage_35 db "Error: cannot assemble the line - unknown mnemonic.",0 szErrMessage_36 db "Error: cannot assemble the line - bad branch destination.",0 szErrMessage_37 db "Error: cannot assemble the line - invalid addressing mode.",0 szErrMessage_38 db "Failed execution error - unknown instruction:",0 szErrMessage_39 db "Error: invalid chars in binary number.",0 szErrMessage_40 db "Error: too many digits in binary number.",0 szErrMessage_41 db "Error: the pseudo op must have an operand.",0 szErrMessage_42 db "Error: bad input - enter a valid symbol or hex address.",0 szErrMessage_43 db "Error: output buffer overflow - cannot finish compile.",0 bfDisplay rb 32768 bfAsmCode rb 32768 bfOutput rb 32768 pOutput dd 0 ; ------------------------------------------------------------------------------------- section '.rc' resource data readable directory RT_DIALOG,dialogs resource dialogs,\ IDD_EDIT_DIALOG,LANG_ENGLISH+SUBLANG_DEFAULT,the_edit_dialog,\ IDD_RUN_DIALOG,LANG_ENGLISH+SUBLANG_DEFAULT,the_run_dialog,\ IDD_WATCH_DIALOG,LANG_ENGLISH+SUBLANG_DEFAULT,the_watch_dialog dialog the_edit_dialog,\ '6502 Assembly Language Simulator',20,50,522,396,\ DS_MODALFRAME+WS_MINIMIZEBOX+WS_POPUP+WS_VISIBLE+WS_CAPTION+WS_SYSMENU,\ 0,0,"Lucida Console",11 dialogitem 'EDIT',0,IDC_INPUT,0,0,260,366,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_OUTPUT,261,0,260,366,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'BUTTON',"Compile Assembly",IDC_BTN_COMPILE,7,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"View Output",IDC_BTN_VIEW_ASM,89,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"View Symbols",IDC_BTN_VIEW_SYM,171,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Clear Assembly",IDC_BTN_CLR_ASM,253,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Execute Code",IDC_BTN_NEXT_DLG,335,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 enddialog dialog the_run_dialog,\ '6502 Assembly Language Simulator',20,50,522,396,\ DS_MODALFRAME+WS_MINIMIZEBOX+WS_POPUP+WS_VISIBLE+WS_CAPTION+WS_SYSMENU,\ 0,0,"Lucida Console",11 dialogitem 'EDIT',0,IDC_OUTPUT,0,0,260,206,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_DEBUG,0,207,260,78,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_STATUS,0,286,260,78,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_PAGES,262,0,260,280,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_ASCII_IO,262,303,260,60,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'BUTTON',"Run Code",IDC_BTN_RUN,7,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Step",IDC_BTN_STEP,89,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Reset PC",IDC_BTN_RESET_PC,171,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Reset Machine",IDC_BTN_RESET,253,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"View Watch",IDC_BTN_VIEW_WATCH,335,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Edit Code",IDC_BTN_PREV_DLG,417,375,80,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'COMBOBOX',"",IDC_CBX_PAGE_SELECT,262,286,80,80,CBS_DROPDOWNLIST+WS_VSCROLL+WS_VISIBLE dialogitem 'BUTTON',"Load ASCII",IDC_BTN_LOAD_ASC,344,286,80,12,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Add To Watch",IDC_BTN_ADD_WATCH,426,286,80,12,BS_PUSHBUTTON+WS_VISIBLE,0 enddialog dialog the_watch_dialog,\ 'Add To The Watch',50,80,200,100,\ DS_MODALFRAME+WS_POPUP+WS_VISIBLE+WS_CAPTION+WS_SYSMENU,\ 0,0,"Lucida Console",11 dialogitem "BUTTON","",IDC_GRP_BOX,3,2,194,92,BS_GROUPBOX+WS_VISIBLE,0 dialogitem "STATIC","Enter a symbol name or hex address:",IDC_PROMPT_1,10,12,180,20,SS_LEFT+WS_GROUP+WS_VISIBLE,0 dialogitem "STATIC","Enter the number of bytes to include:",IDC_PROMPT_2,10,42,180,20,SS_LEFT+WS_GROUP+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_WATCH_ITEM,10,24,180,12,WS_BORDER+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_WATCH_NBYTES,10,54,180,12,WS_BORDER+WS_VISIBLE,0 dialogitem 'BUTTON',"Add",IDC_BTN_ADD,10,73,40,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Close",IDC_BTN_CLOSE,52,73,40,14,BS_PUSHBUTTON+WS_VISIBLE,0 enddialog ; ------------------------------------------------------------------------------------- |