commit 7a6799d2c775a0320d059d7d420e15cb31015099 Author: Ed94 Date: Tue Jan 18 08:15:28 2022 -0500 initial commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..32df2dd --- /dev/null +++ b/.editorconfig @@ -0,0 +1,36 @@ +# root = true + +[*] +end_of_line = lf +insert_final_newline = true +guidelines = 160 + +[*{.h, .c}] +indent_style = tab +indent_size = 4 +guidelines = 160 + +[*{.low.h, .low.c] +indent_style = tab +indent_size = 8 +guidelines = 80 + +[*{.hpp, cpp}] +indent_style = tab +indent_size = 4 +guidelines = 160 + +[*{.low.hpp, .low.cpp}] +indent_style = tab +indent_size = 8 +guidelines = 80 + +[*{.py}] +indent_style = space +indent_size = 4 +guidelines = 180 + +[*[.s]] +indent_style = tab +indent_size = 8 +guidelines = 80 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8929a4c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "editor.rulers": [ + 110, + ], + "editor.cursorStyle": "block-outline" +} diff --git a/0.Hello/16bit.hello.TextModeBuff.hex b/0.Hello/16bit.hello.TextModeBuff.hex new file mode 100644 index 0000000..e9d8fba Binary files /dev/null and b/0.Hello/16bit.hello.TextModeBuff.hex differ diff --git a/0.Hello/16bit.hello.TextModeBuff.hex.s b/0.Hello/16bit.hello.TextModeBuff.hex.s new file mode 100644 index 0000000..31c8832 --- /dev/null +++ b/0.Hello/16bit.hello.TextModeBuff.hex.s @@ -0,0 +1,164 @@ +; Print HEx + +; x86 +; 16-bit - Real Mode, V86 Mode + +; https://codereview.stackexchange.com/questions/230755/display-hexadecimal-value-stored-at-a-register + + +%include "AAL.x86.S" + + +; 16-Bit Mode +[BITS 16] +; The ORG directive specifies the starting address of a segment +[ORG Mem_BootSector_Start] + + +start: + mov BX, Mem_BootSector_Start + +; textmode_ClearScreen +; Params + mov AH, Video_SetMode + mov AL, VideoMode_Text_80x25 +; Call Interrupt +int VideoService + +; Exclusive-OR (xor'ing a value to itself zeros the value) + xor AX, AX +; Set Data Segment and Extra Segment to 0x0000 + mov DS, AX + mov ES, AX +; Set Stack Segment (SS) to to 0x0000 + mov SS, AX +; Set Stack Pointer (SP) to the start of the boot sector. + mov SP, BX + + mov BX, 0x2022 +call output_Hex + +; Idle +hang : +jmp short hang + + +;============================================================================================================= +; Output Hex to TextMode via Teletype +;============================================================================================================= +%define hex BX +%define backup CX + +output_Hex: +; Clear Interrupt Flag : Prevents interrupts form occuring + cli +; Push all registers values onto the stack + pusha + +; Store original value in backup + mov backup, hex +; Setup referfence to hex chars memory + mov SI, .CharHex + +; Shift Logical Right : SHR performs an unsigned divide +; The high-order bit is set to 0. +; 0b1000 -> 0b0100, 0b0001 -> 0b0000 + shr hex, 12 ; First four : 0x[#]### -> 0x000# + and hex, 0x0F ; Mask out any garbage + mov AL, [hex + SI] ; AL = hex + SI + mov [.Result + 2], AL ; result[2] = AL + + mov hex, backup ; Next four + shr hex, 8 + and hex, 0x0F + mov AL, [hex + SI] + mov [.Result + 3], AL + + mov hex, backup ; ... + shr hex, 4 + and hex, 0x0F + mov AL, [hex + SI] + mov [.Result + 4], AL + + mov hex, backup + shr hex, 0 + and hex, 0x0F + mov AL, [hex + SI] + mov [.Result + 5], AL + +; BX : String arg + mov CX, .Result +call output_String + +; Pop all register values that were saved on the current stack + popa +; Set Interrupt Flag : Restore interrupts + ret + +; Proc Data +.CharHex: +db '0123456789ABCDEF', 0x0 + +.Result: +db '0x0000', 0x0 + +%undef hex +%undef backup +%unmacro index 1 + + +;============================================================================================================= +; Output String to TextMode via Teletype +;============================================================================================================= +%define string CX +%define CharHex_Length 6 +%macro TextMode_SetChar 2 + mov word [%1 * 2 ], %2 + mov word [%1 * 2 + 1], 0x0F +%endmacro +output_String: + pusha +; Will track string index + mov SI, 0x0 + +; Prep BH and AH with Teletype video service option + mov BH, 0x0 + mov AH, Video_TeleType + +; Reg CX cannot be used as an index speciifer. [BX] is +; SI can be used as an offset inside [BX + offset] + mov BX, CX + +.loop: +; Compare + cmp SI, CharHex_Length + je .break +; Jump + +; Print via teletype + mov AL, [BX + SI]; +int VideoService + +; Increment index + inc SI + jmp short .loop + +.break: + popa + ret + +%undef string +%undef index +%undef CharHex_Length +%unmacro TextMode_SetChar 2 + + + +;============================================================================================================= +; Wrap up +;============================================================================================================= +; Byte pad 512 bytes (zeroed) +times 510-$+start db 0 +; Master Boot Record signature +db 0x55 +db 0xAA diff --git a/0.Hello/16bit.hello.char.TextModeBuff.s b/0.Hello/16bit.hello.char.TextModeBuff.s new file mode 100644 index 0000000..298f8ba --- /dev/null +++ b/0.Hello/16bit.hello.char.TextModeBuff.s @@ -0,0 +1,58 @@ +; Hello world. + +; x86 +; 16-bit - Real Mode, V86 Mode + +%include "AAL.x86.S" + + +; 16-Bit Mode +[BITS 16] +; The ORG directive specifies the starting address of a segment +[ORG Mem_BootSector_Start] + + +; A label to the address in memory +; Auto calculated by the assembler +start : + +textmode_ClearScreen : +; Params + mov AH, Video_SetMode + mov AL, VideoMode_Text_80x25 +; Call Interrupt +int VideoService + +; Set Data segment to the text mode's memory buffer +mov AX, Video_Text_MemBuffer +mov DS, AX + +%macro SetChar 2 + ; word : 16-bit (2-byte) increments + ; [offset] : specifies offset in Data Segment (DS) + ; Character + mov word [%1 * 2 ], %2 + ; Attributes - Low: Black, High: White + mov word [%1 * 2 + 1], 0x0F +%endmacro + SetChar 0x00, 'H' + SetChar 0x01, 'e' + SetChar 0x02, 'l' + SetChar 0x03, 'l' + SetChar 0x04, 'o' + SetChar 0x05, ' ' + SetChar 0x06, 'W' + SetChar 0x07, 'o' + SetChar 0x08, 'r' + SetChar 0x09, 'l' + SetChar 0x0A, 'd' + +hang : +jmp short hang + + +; Byte pad 512 bytes (zeroed) +times 510-$+start db 0 +; Master Boot Record signature +db 0x55 +db 0xAA diff --git a/0.Hello/16bit.hello.char.teletype.s b/0.Hello/16bit.hello.char.teletype.s new file mode 100644 index 0000000..fb53f74 --- /dev/null +++ b/0.Hello/16bit.hello.char.teletype.s @@ -0,0 +1,60 @@ +; Hello world. + +; x86 +; 16-bit - Real Mode, V86 Mode + +%include "AAL.x86.S" + + +; 16-Bit Mode +[BITS 16] +; The ORG directive specifies the starting address of a segment +[ORG Mem_BootSector_Start] + + +start : + +textmode_ClearScreen: +; Params + mov AH, Video_SetMode + mov AL, VideoMode_Text_40x25 +; Call Interrupt +int VideoService + +teletype_HelloWorld : + mov BH, 0x0 ; Make sure the Active page is the first + mov AH, Video_TeleType + mov AL, 'H' +int VideoService + mov AL, 'e' +int VideoService + mov AL, 'l' +int VideoService + mov AL, 'l' +int VideoService + mov AL, 'l' +int VideoService + mov AL, 'o' +int VideoService + mov AL, ' ' +int VideoService + mov AL, 'W' +int VideoService + mov AL, 'o' +int VideoService + mov AL, 'r' +int VideoService + mov AL, 'l' +int VideoService + mov AL, 'd' +int VideoService + +hang : +jmp short hang + + +; Byte pad 512 bytes (zeroed) +times 510-$+start db 0 +; Master Boot Record signature +db 0x55 +db 0xAA diff --git a/0.Hello/AAL.x86.s b/0.Hello/AAL.x86.s new file mode 100644 index 0000000..3e7104e --- /dev/null +++ b/0.Hello/AAL.x86.s @@ -0,0 +1,349 @@ +;============================================================================================================= +;============================================================================================================= +;============================================================================================================= +; AAL - Assembly Abstraction layer +; x86-64 +; Provides a suite of docs, functionatliy, macros, etc. +; +; Made while learning x86 +; Edward R. Gonzalez +;============================================================================================================= +;============================================================================================================= +;============================================================================================================= +; +; See +; https://en.wikibooks.org/wiki/X86_Assembly/16,_32,_and_64_Bits +; https://wiki.osdev.org/X86-64 +; http://www.ctyme.com/rbrown.htm +; https://github.com/Captainarash/The_Holy_Book_of_X86/blob/master/book_vol_1.txt + + +;============================================================================================================= +; Calling Convention +;============================================================================================================= +; Calling convention - Caller/Callee Saved Registers +; +; Caller rules: When calling a function the registers +; RAX, RCX, RDX, R8, R9, R10, R11 are considered volatile and must be saved into the stack +; by the caller, if it relies on them +; (unless otherwise safety-provable by analysis such as whole program optimization). +; +; Callee rules: +; RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 +; are considered nonvolatile and must be saved and restored from the stack by the callee if it modify them. +;============================================================================================================= +; END OF CALLING CONVENTION +;============================================================================================================= + +;============================================================================================================= +; Register Documentation +;============================================================================================================= +; General Purpose +; 8 High Low 16 32 64 Intended Purpose +; AH AL AX EAX RAX Accumulator +; BH BL BX EBX RBX Base +; CH CL CX ECX RCX Counter +; DH DL DX EDX RDX Data (Used to extend the A register) +; SIL SI ESI RSI Source index for strings ops +; DIL DI EDI RDI Destination index for string operations +; SPL SPL ESP RSP Stack pointer +; BPL BP EBP RBP Base pointer (meant for stack frames) +; R8B R8W R8D R8 General Purpose (and below) +; R9B R9W R9D R9 +; R10B R10W R10D R10 +; R11B R11W R11D R11 +; R12B R12W R12D R12 +; R13B R13W R13D R13 +; R14B R14W R14D R14 +; R15B R15W R15D R15 +; Instruction Pointer +; 16 32 64 +; IP EIP RIP +; Segment +; 16 +; CS Code Segment +; DS Data Segment +; SS Stack Segment +; ES Extra Segment +; FS General-purpose +; GS General-purpose +; RFLAGS +; Bit(s) Label Description +; 0 CF Carry Flag +; 1 1 Reserved +; 2 PF Parity Flag +; 3 0 Reserved +; 4 AF Auxiliary Carry Flag +; 5 0 Reserved +; 6 ZF Zero Flag +; 7 SF Sign Flag +; 8 TF Trap Flag +; 9 IF Interrupt Enable Flag +; 10 DF Direction Flag +; 11 OF Overflow Flag +; 12-13 IOPL I/O Privilege Level +; 14 NT Nested Task +; 15 0 Reserved +; 16 RF Resume Flag +; 17 VM Virtual-8086 Mode +; 18 AC Alignment Check / Access Control +; 19 VIF Virtual Interrupt Flag +; 20 VIP Virtual Interrupt Pending +; 21 ID ID Flag +; 22-63 0 Reserved + +; Control +; CR0 +; Bit(s) Label Description +; 0 PE Protected Mode Enable +; 1 MP Monitor Co-Processor +; 2 EM Emulation +; 3 TS Task Switched +; 4 ET Extension Type +; 5 NE Numeric Error +; 6-15 0 Reserved +; 16 WP Write Protect +; 17 0 Reserved +; 18 AM Alignment Mask +; 19-28 0 Reserved +; 29 NW Not-Write Through +; 30 CD Cache Disable +; 31 PG Paging +; 32-63 0 Reserved +; CR2 +; Contains the linear (virtual) address which triggered a page fault, available in the page fault's interrupt handler. +; +; CR3 +; Bit(s) Label Description Condition +; 0-11 0-2 0 Reserved CR4.PCIDE = 0 +; 3 PWT Page-Level Write Through +; 5 PCD Page-Level Cache Disable +; 5-11 0 Reserved +; 0-11 PCID CR4.PCIDE = 1 +; 12-63 Physical Base Address of the PML4 +; +; Note that this must be page aligned +; +; CR4 +; Bit(s) Label Description +; 0 VME Virtual-8086 Mode Extensions +; 1 PVI Protected Mode Virtual Interrupts +; 2 TSD Time Stamp enabled only in ring 0 +; 3 DE Debugging Extensions +; 4 PSE Page Size Extension +; 5 PAE Physical Address Extension +; 6 MCE Machine Check Exception +; 7 PGE Page Global Enable +; 8 PCE Performance Monitoring Counter Enable +; 9 OSFXSR OS support for fxsave and fxrstor instructions +; 10 OSXMMEXCPT OS Support for unmasked simd floating point exceptions +; 11 UMIP User-Mode Instruction Prevention (SGDT, SIDT, SLDT, SMSW, and STR are disabled in user mode) +; 12 0 Reserved +; 13 VMXE Virtual Machine Extensions Enable +; 14 SMXE Safer Mode Extensions Enable +; 15 0 Reserved +; 17 PCIDE PCID Enable +; 18 OSXSAVE XSAVE And Processor Extended States Enable +; 19 0 Reserved +; 20 SMEP Supervisor Mode Executions Protection Enable +; 21 SMAP Supervisor Mode Access Protection Enable +; 22 PKE Enable protection keys for user-mode pages +; 23 CET Enable Control-flow Enforcement Technology +; 24 PKS Enable protection keys for supervisor-mode pages +; 25-63 0 Reserved +; CR8 +; CR8 is a new register accessible in 64-bit mode using the REX prefix. +; CR8 is used to prioritize external interrupts and is referred to as the task-priority register (TPR). +; +; The AMD64 architecture allows software to define up to 15 external interrupt-priority classes. +; Priority classes are numbered from 1 to 15, with priority-class 1 being the lowest and priority-class 15 the highest. +; CR8 uses the four low-order bits for specifying a task priority and the remaining 60 bits are reserved and must be written with zeros. +; +; System software can use the TPR register to temporarily block low-priority interrupts from interrupting a high-priority task. +; This is accomplished by loading TPR with a value corresponding to the highest-priority interrupt that is to be blocked. +; For example, loading TPR with a value of 9 (1001b) blocks all interrupts with a priority class of 9 or less, +; while allowing all interrupts with a priority class of 10 or more to be recognized. +; Loading TPR with 0 enables all external interrupts. Loading TPR with 15 (1111b) disables all external interrupts. +; +; The TPR is cleared to 0 on reset. +; Bit Purpose +; 0-3 Priority +; 4-63 Reserved +; CR1, CR5-7, CR9-15 +; Reserved, the cpu will throw a #ud exeption when trying to access them. +; +; CR1, CR5-7, CR9-15 +; Reserved, the cpu will throw a #ud exeption when trying to access them. +; +; MSRs +; +; IA32_EFER +; Extended Feature Enable Register (EFER) is a model-specific register added in the AMD K6 processor, +; to allow enabling the SYSCALL/SYSRET instruction, and later for entering and exiting long mode. +; This register becomes architectural in AMD64 and has been adopted by Intel. Its MSR number is 0xC0000080. +; +; Bit(s) Label Description +; 0 SCE System Call Extensions +; 1-7 0 Reserved +; 8 LME Long Mode Enable +; 10 LMA Long Mode Active +; 11 NXE No-Execute Enable +; 12 SVME Secure Virtual Machine Enable +; 13 LMSLE Long Mode Segment Limit Enable +; 14 FFXSR Fast FXSAVE/FXRSTOR +; 15 TCE Translation Cache Extension +; 16-63 0 Reserved +; +; FS.base, GS.base +; +; MSRs with the addresses 0xC0000100 (for FS) and 0xC0000101 (for GS) contain the base addresses of the FS and GS segment registers. +; These are commonly used for thread-pointers in user code and CPU-local pointers in kernel code. Safe to contain anything, +; since use of a segment does not confer additional privileges to user code. +; +; In newer CPUs, these can also be written with WRFSBASE and WRGSBASE instructions at any privilege level. +; +; KernelGSBase +; MSR with the address 0xC0000102. +; Is basically a buffer that gets exchanged with GS.base after a swapgs instruction. +; Usually used to seperate kernel and user use of the GS register. +; +; Debug Registers +; +; DR0 - DR3 +; Contain linear addresses of up to 4 breakpoints. If paging is enabled, they are translated to physical addresses. +; DR6 +; It permits the debugger to determine which debug conditions have occured. +; When an enabled debug exception is enabled, low order bits 0-3 are set before entering debug exception handler. +; DR7 +; Bit Description +; 0 Local DR0 Breakpoint +; 1 Global DR0 Breakpoint +; 2 Local DR1 Breakpoint +; 3 Global DR1 Breakpoint +; 4 Local DR2 Breakpoint +; 5 Global DR2 Breakpoint +; 6 Local DR3 Breakpoint +; 7 Global DR3 Breakpoint +; 16-17 Conditions for DR0 +; 18-19 Size of DR0 Breakpoint +; 20-21 Conditions for DR1 +; 22-23 Size of DR1 Breakpoint +; 24-25 Conditions for DR2 +; 26-27 Size of DR2 Breakpoint +; 28-29 Conditions for DR3 +; 30-31 Size of DR3 Breakpoint +; +; A local breakpoint bit deactivates on hardware task switches, while a global does not. +; 00b condition means execution break, 01b means a write watchpoint, and 11b means an R/W watchpoint. +; 10b is reserved for I/O R/W (unsupported). +; +; Test Registers +; Name Description +; TR3 - TR5 Undocumented +; TR6 Test Command Register +; TR7 Test Data Register +; +; Protected Mode Registers +; GDTR +; +; Operand Size Label Description +; 64-bit 32-bit +; Bits 0-15 (Same) Limit Size of GDT +; Bits 16-79 Bits 16-47 Base Starting Address of GDT +; +; LDTR +; Stores the segment selector of the LDT. +; +; TR +; Stores the segment selector of the TSS. +; +; IDTR +; Operand Size Label Description +; 64-bit 32-bit +; Bits 0-15 (Same) Limit Size of IDT +; Bits 16-79 Bits 16-47 Base Starting Address of IDT +;============================================================================================================= +; END OF REGISTER DOCUMENTATION +;============================================================================================================= + +%ifndef AAL_x86_Def +;============================================================================================================= +; Instructions Library +;============================================================================================================= +; NO-Operation : Exchanges value of rax with rax to achieve nothing. +%define nop XCHG rax, rax +;============================================================================================================= +; END - Instructions Library +;============================================================================================================= + +;============================================================================================================= +; Interrupts +;============================================================================================================= +; BIOS + +; CX, DX Interval in microseconds +; CX : High, DX : Low +; SystemService +%define BIOS_Wait 0x86 + +; Memory + +; Real Mode - Conventional Lower Memory +%define Mem_RM_CLower_Start 0x0500 +%define Mem_RM_CLower_End 0x7BFF +; 2 Byte Boundary Alignment +%define Mem_RM_CLower_2BB_End 0x7BE0 + +; Real Mode - Conventional Upper memory +%define Mem_RM_CUpper_Start 0x7E00 +%define Mem_RM_CUpper_End 0x7FFF +; 2 Byte Boundary Alignment +%define Mem_RM_CUpper_2BB_End 0x7FE0 + +; Real Mode - OS Boot Sector +%define Mem_BootSector_Start 0x7C00 +%define Mem_BootSector_512 0x7CFE +%define Mem_BootSector_End 0x7DFF + +; Misc System Services +%define SystemService 0x15 + +; Video +%define VideoService 0x10 + +; Returns +; AH = Number of character columns +; AL = Display mode +; BH = Active Page +%define Video_GetCurrentMode 0x0F + +; Used to set the video mode. +%define Video_SetMode 0x00 + +; SetVideoMode - Modes +; cbOff : Color Burst Off +%define VideoMode_Text_40x25_cbOff 0x00 +%define VideoMode_Text_40x25 0x01 +%define VideoMode_Text_80x25_cbOff 0x02 +%define VideoMode_Text_80x25 0x03 +%define VideoMode_Graphics_320x200 0x04 +%define VideoMode_Graphics_320x200_cboff 0x05 +%define VideoMode_Graphics_640x200 0x06 + +; Output a character +%define Video_TeleType 0xE +; Where memory buffer for Video's Text mode starts +%define Video_Text_MemBuffer 0xB800 +;============================================================================================================= +; END - Interrupts +;============================================================================================================= + + +%define char_CR 0xD ; Carriage Return +%define char_LF 0xA ; Line Feed + + +%define AAL_x86_Def +%endif + + diff --git a/16bit copy.Scratch b/16bit copy.Scratch new file mode 100644 index 0000000..da660c5 Binary files /dev/null and b/16bit copy.Scratch differ diff --git a/16bit.CheckDisplayMode.s b/16bit.CheckDisplayMode.s new file mode 100644 index 0000000..c7dbfd6 --- /dev/null +++ b/16bit.CheckDisplayMode.s @@ -0,0 +1,53 @@ +; TODO: Finish? +; Hello world. + +; x86 +; 16-bit - Real Mode, V86 Mode + + +%include "AAL.x86.S" + + +; 16-Bit Mode +[BITS 16] + + +; The ORG directive specifies the starting address of a segment +[ORG BIOS_LoadCode_Address] + + +start : + +textmode_ClearScreen : +; Params + mov AH, Video_SetMode + mov AL, VideoMode_Text_40x25 +; Call Interrupt +int VideoService + +textmode_CheckDisplayMode : + mov AH, Video_GetCurrentMode +int VideoService +; Return Values + mov BH, AH + mov BL, AL + +; Print Cols + mov AH, Video_TeleType + mov AL, BH +int VideoService +; Print Mode + mov AH, Video_TeleType + mov AL, BL +int VideoService + + +hang : +jmp short ang + + +; Byte pad 512 bytes (zeroed) +times 510-$+start db 0 +; Master Boot Record signature +db 0x55 +db 0xAA diff --git a/16bit.Scratch b/16bit.Scratch new file mode 100644 index 0000000..da660c5 Binary files /dev/null and b/16bit.Scratch differ diff --git a/16bit.Scratch.s b/16bit.Scratch.s new file mode 100644 index 0000000..80a1944 --- /dev/null +++ b/16bit.Scratch.s @@ -0,0 +1,163 @@ +; Print HEx + +; x86 +; 16-bit - Real Mode, V86 Mode + +; https://codereview.stackexchange.com/questions/230755/display-hexadecimal-value-stored-at-a-register + + +%include "AAL.x86.S" +%include "AAL.x86.routines.macros.S" + + +; 16-Bit Mode +[BITS 16] +; The ORG directive specifies the starting address of a segment +[ORG Mem_BootSector_Start] + + +;============================================================================================================= +; Boot Sector Code +;============================================================================================================= +start: +Video_SetTextMode_80x25 + +; Exclusive-OR (xor'ing a value to itself zeros the value) + xor AX, AX +; Set Data Segment and Extra Segment to 0x0000 + mov DS, AX + mov ES, AX +; Set Stack Segment (SS) to to 0x0000 + mov SS, AX +; Set Stack Pointer (SP) to the start of the boot sector. + mov BX, Mem_BootSector_Start + mov SP, BX + +; String testing +String_Out TestStr, [TestStr_len] + + mov AH, BIOS_Wait + mov CX, 0x02 +int SystemService + +; Hex Testing +String_Out HexTest, [HexTest_len] +Hex16_ToString [HexNum], HexString +Hex16_ToString [HexNumT], HexStringT +String_Out ResultStr, [ResultStr_len] +String_Out HexString, 4 +String_Out HexStringT, 4 + + mov AH, BIOS_Wait + mov CX, 0x10 +int SystemService + +Char_Out char_LF +Char_Out char_CR + + mov BX, 0x7C00 + ; sub BX, 0x7DFF + ; mov BX, 0x0000 + mov DX, 512 +call dump_out + +; Idle +hang : +jmp short hang + + +dump_out: +; Args: +; BX = StartLocation +; CX = ByteCount +%define StartLocation BX +%define ByteCount DX + push BX + push SI + ; xor BX, BX + xor SI, SI + +.loop: + cmp SI, ByteCount + je .break + + + push BX + push DX + push SI + mov AX, StartLocation + add AX, SI + +Hex16_ToString AX, .HexStr +String_Out .HexStr, 4 + + pop SI + pop DX + pop BX + + mov AH, [StartLocation + SI] + add SI, 1 + + mov AL, [StartLocation + SI] + mov [.HexNum], AX + + push BX + push DX + push SI +Char_Out ' ' + +Hex16_ToString [.HexNum], .HexStr +String_Out .HexStr, 4 + pop SI + pop DX + pop BX + +Char_Out ' ' + + mov AH, BIOS_Wait + mov CX, 0x02 +int SystemService + + ; add SI, 4 + inc SI + jmp .loop + +.break: + pop SI + pop BX +ret + +.HexNum : dw 0x0000 +.HexStr : dw ' ' +%undef StartLocation +%undef WordCount + + +%include "AAL.x86.routines.s" + + +;============================================================================================================= +; Data +;============================================================================================================= +TestStr : db 'String Test', char_LF, char_CR +TestStr_len : dw 13 + +HexTest : db 'Hex Test', char_LF, char_CR +HexTest_len : dw 10 + +HexNum : dw 0x1994 +HexNumT : dw 0x2022 +HexString : db '0000' +HexStringT : db '0000' + +ResultStr : db 'Result: ' +ResultStr_len : db 8 + +;============================================================================================================= +; Wrap up +;============================================================================================================= +; Byte pad 512 bytes (zeroed) +times 510-$+start db 0 +; Master Boot Record signature +db 0x55 +db 0xAA diff --git a/AAL.x86.routines.macros.s b/AAL.x86.routines.macros.s new file mode 100644 index 0000000..ee43a66 --- /dev/null +++ b/AAL.x86.routines.macros.s @@ -0,0 +1,43 @@ +%ifndef AAL_macro_routines_Def +%include "AAL.x86.S" + + +;============================================================================================================= +; Interrupts +;============================================================================================================= + +%macro Video_SetTextMode_80x25 0 + mov AH, Video_SetMode + mov AL, VideoMode_Text_80x25 +int VideoService +%endmacro + +;============================================================================================================= +; Routines +;============================================================================================================= + +%macro Hex16_ToString 2 + mov DX, %1 + mov CX, %2 + push CX +call h16_toString + pop CX +%endmacro + +%macro Char_Out 1 + mov AX, %1 + push AX +call out_char + pop AX +%endmacro + +%macro String_Out 2 + mov BX, %1 + mov AX, %2 + push AX +call out_string + pop AX +%endmacro + +%define AAL_macro_routines_Def +%endif diff --git a/AAL.x86.routines.s b/AAL.x86.routines.s new file mode 100644 index 0000000..cffd735 --- /dev/null +++ b/AAL.x86.routines.s @@ -0,0 +1,117 @@ +%ifndef AAL_routines_Def + +%include "AAL.x86.S" + + +;============================================================================================================= +; Routines +;============================================================================================================= + +; Prints out a 16-bit hex value. +h16_toString: +; Arg - DX : Hex Num +; ArgStr: String +%define argStr BP + 6 + push BX + push BP + mov BP, SP + +; Half-Byte index + push SI + xor SI, SI + +.loop: +; If all 4-bit slots translate, break + cmp SI, 4 + je .break + +; Get latest half-byte from DX + mov AX, DX +; Doing only the first right-most digit + and AX, 0x000F +; Get ASCII numeral or alpha character + add AL, 0x30 +; 0->9 (<= 0x39), A->F (>= 0x39) + cmp AL, 0x39 ; Numeral offset + jle .SetCharVal + add AL, 0x7 ; A-F offset + +.SetCharVal: +; Add the char value to the string + mov BX, [argStr] +; Move to last half-byte + add BX, 3 +; Go to the current half-byte via index offset + sub BX, SI +; Write ascii hex value to half-byte in ArgStr + mov [BX], AL +; Rotate the next half-byte over + ror DX, 4 + + inc SI + jmp .loop + +.break: + pop SI + pop BP + pop BX +%undef argStr +ret + + +; Print out an ASCII character. +out_char: +%define arg1 BP + 6 + push BX + push BP + mov BP, SP + + mov AH, Video_TeleType + mov AL, [arg1] +int VideoService + + pop BP + pop BX +%undef arg1 +ret + + +; Print out an ascii string of speicifed length +out_string: +; Arg - BX: String +%define argLen BP + 4 ; String Length +; Store previous state of BP and set it to SP + ; pusha ; 14 bytes + push BP ; 4 bytes + mov BP, SP +; Using the source index + push SI ; 0 bytes... + xor SI, SI + +; Backup BX for later + mov CX, BX + mov AH, Video_TeleType + +.loop: +; Bounds check + cmp SI, [argLen] + je .break + +; Output a character + mov BX, CX + mov AL, [BX + SI] + xor BH, BH ; Clear BH for correct active page +int VideoService + + add SI, 0x1 + jmp .loop + +.break: + pop SI + pop BP +%undef argLen +ret + + +%define AAL_routines_Def +%endif diff --git a/AAL.x86.s b/AAL.x86.s new file mode 100644 index 0000000..1e87daf --- /dev/null +++ b/AAL.x86.s @@ -0,0 +1,362 @@ +;============================================================================================================= +;============================================================================================================= +;============================================================================================================= +; AAL - Assembly Abstraction layer +; x86-64 +; Provides a suite of docs, functionatliy, macros, etc. +; +; Made while learning x86 +; Edward R. Gonzalez +;============================================================================================================= +;============================================================================================================= +;============================================================================================================= +; +; See +; https://en.wikibooks.org/wiki/X86_Assembly/16,_32,_and_64_Bits +; https://wiki.osdev.org/X86-64 +; http://www.ctyme.com/rbrown.htm +; https://github.com/Captainarash/The_Holy_Book_of_X86/blob/master/book_vol_1.txt + + +;============================================================================================================= +; Calling Convention +;============================================================================================================= +; Calling convention - Caller/Callee Saved Registers +; +; Caller rules: When calling a function the registers +; RAX, RCX, RDX, R8, R9, R10, R11 are considered volatile and must be saved into the stack +; by the caller, if it relies on them +; (unless otherwise safety-provable by analysis such as whole program optimization). +; +; Callee rules: +; RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 +; are considered nonvolatile and must be saved and restored from the stack by the callee if it modify them. +;============================================================================================================= +; END OF CALLING CONVENTION +;============================================================================================================= + +;============================================================================================================= +; Register Documentation +;============================================================================================================= +; General Purpose +; 8 High Low 16 32 64 Intended Purpose +; AH AL AX EAX RAX Accumulator +; BH BL BX EBX RBX Base +; CH CL CX ECX RCX Counter +; DH DL DX EDX RDX Data (Used to extend the A register) +; SIL SI ESI RSI Source index for strings ops +; DIL DI EDI RDI Destination index for string operations +; SPL SPL ESP RSP Stack pointer +; BPL BP EBP RBP Base pointer (meant for stack frames) +; R8B R8W R8D R8 General Purpose (and below) +; R9B R9W R9D R9 +; R10B R10W R10D R10 +; R11B R11W R11D R11 +; R12B R12W R12D R12 +; R13B R13W R13D R13 +; R14B R14W R14D R14 +; R15B R15W R15D R15 +; Instruction Pointer +; 16 32 64 +; IP EIP RIP +; Segment +; 16 +; CS Code Segment +; DS Data Segment +; SS Stack Segment +; ES Extra Segment +; FS General-purpose +; GS General-purpose +; RFLAGS +; Bit(s) Label Description +; 0 CF Carry Flag +; 1 1 Reserved +; 2 PF Parity Flag +; 3 0 Reserved +; 4 AF Auxiliary Carry Flag +; 5 0 Reserved +; 6 ZF Zero Flag +; 7 SF Sign Flag +; 8 TF Trap Flag +; 9 IF Interrupt Enable Flag +; 10 DF Direction Flag +; 11 OF Overflow Flag +; 12-13 IOPL I/O Privilege Level +; 14 NT Nested Task +; 15 0 Reserved +; 16 RF Resume Flag +; 17 VM Virtual-8086 Mode +; 18 AC Alignment Check / Access Control +; 19 VIF Virtual Interrupt Flag +; 20 VIP Virtual Interrupt Pending +; 21 ID ID Flag +; 22-63 0 Reserved + +; Control +; CR0 +; Bit(s) Label Description +; 0 PE Protected Mode Enable +; 1 MP Monitor Co-Processor +; 2 EM Emulation +; 3 TS Task Switched +; 4 ET Extension Type +; 5 NE Numeric Error +; 6-15 0 Reserved +; 16 WP Write Protect +; 17 0 Reserved +; 18 AM Alignment Mask +; 19-28 0 Reserved +; 29 NW Not-Write Through +; 30 CD Cache Disable +; 31 PG Paging +; 32-63 0 Reserved +; CR2 +; Contains the linear (virtual) address which triggered a page fault, available in the page fault's interrupt handler. +; +; CR3 +; Bit(s) Label Description Condition +; 0-11 0-2 0 Reserved CR4.PCIDE = 0 +; 3 PWT Page-Level Write Through +; 5 PCD Page-Level Cache Disable +; 5-11 0 Reserved +; 0-11 PCID CR4.PCIDE = 1 +; 12-63 Physical Base Address of the PML4 +; +; Note that this must be page aligned +; +; CR4 +; Bit(s) Label Description +; 0 VME Virtual-8086 Mode Extensions +; 1 PVI Protected Mode Virtual Interrupts +; 2 TSD Time Stamp enabled only in ring 0 +; 3 DE Debugging Extensions +; 4 PSE Page Size Extension +; 5 PAE Physical Address Extension +; 6 MCE Machine Check Exception +; 7 PGE Page Global Enable +; 8 PCE Performance Monitoring Counter Enable +; 9 OSFXSR OS support for fxsave and fxrstor instructions +; 10 OSXMMEXCPT OS Support for unmasked simd floating point exceptions +; 11 UMIP User-Mode Instruction Prevention (SGDT, SIDT, SLDT, SMSW, and STR are disabled in user mode) +; 12 0 Reserved +; 13 VMXE Virtual Machine Extensions Enable +; 14 SMXE Safer Mode Extensions Enable +; 15 0 Reserved +; 17 PCIDE PCID Enable +; 18 OSXSAVE XSAVE And Processor Extended States Enable +; 19 0 Reserved +; 20 SMEP Supervisor Mode Executions Protection Enable +; 21 SMAP Supervisor Mode Access Protection Enable +; 22 PKE Enable protection keys for user-mode pages +; 23 CET Enable Control-flow Enforcement Technology +; 24 PKS Enable protection keys for supervisor-mode pages +; 25-63 0 Reserved +; CR8 +; CR8 is a new register accessible in 64-bit mode using the REX prefix. +; CR8 is used to prioritize external interrupts and is referred to as the task-priority register (TPR). +; +; The AMD64 architecture allows software to define up to 15 external interrupt-priority classes. +; Priority classes are numbered from 1 to 15, with priority-class 1 being the lowest and priority-class 15 the highest. +; CR8 uses the four low-order bits for specifying a task priority and the remaining 60 bits are reserved and must be written with zeros. +; +; System software can use the TPR register to temporarily block low-priority interrupts from interrupting a high-priority task. +; This is accomplished by loading TPR with a value corresponding to the highest-priority interrupt that is to be blocked. +; For example, loading TPR with a value of 9 (1001b) blocks all interrupts with a priority class of 9 or less, +; while allowing all interrupts with a priority class of 10 or more to be recognized. +; Loading TPR with 0 enables all external interrupts. Loading TPR with 15 (1111b) disables all external interrupts. +; +; The TPR is cleared to 0 on reset. +; Bit Purpose +; 0-3 Priority +; 4-63 Reserved +; CR1, CR5-7, CR9-15 +; Reserved, the cpu will throw a #ud exeption when trying to access them. +; +; CR1, CR5-7, CR9-15 +; Reserved, the cpu will throw a #ud exeption when trying to access them. +; +; MSRs +; +; IA32_EFER +; Extended Feature Enable Register (EFER) is a model-specific register added in the AMD K6 processor, +; to allow enabling the SYSCALL/SYSRET instruction, and later for entering and exiting long mode. +; This register becomes architectural in AMD64 and has been adopted by Intel. Its MSR number is 0xC0000080. +; +; Bit(s) Label Description +; 0 SCE System Call Extensions +; 1-7 0 Reserved +; 8 LME Long Mode Enable +; 10 LMA Long Mode Active +; 11 NXE No-Execute Enable +; 12 SVME Secure Virtual Machine Enable +; 13 LMSLE Long Mode Segment Limit Enable +; 14 FFXSR Fast FXSAVE/FXRSTOR +; 15 TCE Translation Cache Extension +; 16-63 0 Reserved +; +; FS.base, GS.base +; +; MSRs with the addresses 0xC0000100 (for FS) and 0xC0000101 (for GS) contain the base addresses of the FS and GS segment registers. +; These are commonly used for thread-pointers in user code and CPU-local pointers in kernel code. Safe to contain anything, +; since use of a segment does not confer additional privileges to user code. +; +; In newer CPUs, these can also be written with WRFSBASE and WRGSBASE instructions at any privilege level. +; +; KernelGSBase +; MSR with the address 0xC0000102. +; Is basically a buffer that gets exchanged with GS.base after a swapgs instruction. +; Usually used to seperate kernel and user use of the GS register. +; +; Debug Registers +; +; DR0 - DR3 +; Contain linear addresses of up to 4 breakpoints. If paging is enabled, they are translated to physical addresses. +; DR6 +; It permits the debugger to determine which debug conditions have occured. +; When an enabled debug exception is enabled, low order bits 0-3 are set before entering debug exception handler. +; DR7 +; Bit Description +; 0 Local DR0 Breakpoint +; 1 Global DR0 Breakpoint +; 2 Local DR1 Breakpoint +; 3 Global DR1 Breakpoint +; 4 Local DR2 Breakpoint +; 5 Global DR2 Breakpoint +; 6 Local DR3 Breakpoint +; 7 Global DR3 Breakpoint +; 16-17 Conditions for DR0 +; 18-19 Size of DR0 Breakpoint +; 20-21 Conditions for DR1 +; 22-23 Size of DR1 Breakpoint +; 24-25 Conditions for DR2 +; 26-27 Size of DR2 Breakpoint +; 28-29 Conditions for DR3 +; 30-31 Size of DR3 Breakpoint +; +; A local breakpoint bit deactivates on hardware task switches, while a global does not. +; 00b condition means execution break, 01b means a write watchpoint, and 11b means an R/W watchpoint. +; 10b is reserved for I/O R/W (unsupported). +; +; Test Registers +; Name Description +; TR3 - TR5 Undocumented +; TR6 Test Command Register +; TR7 Test Data Register +; +; Protected Mode Registers +; GDTR +; +; Operand Size Label Description +; 64-bit 32-bit +; Bits 0-15 (Same) Limit Size of GDT +; Bits 16-79 Bits 16-47 Base Starting Address of GDT +; +; LDTR +; Stores the segment selector of the LDT. +; +; TR +; Stores the segment selector of the TSS. +; +; IDTR +; Operand Size Label Description +; 64-bit 32-bit +; Bits 0-15 (Same) Limit Size of IDT +; Bits 16-79 Bits 16-47 Base Starting Address of IDT +;============================================================================================================= +; END OF REGISTER DOCUMENTATION +;============================================================================================================= + +%ifndef AAL_x86_Def +;============================================================================================================= +; Instructions Library +;============================================================================================================= +; NO-Operation : Exchanges value of rax with rax to achieve nothing. +%define nop XCHG rax, rax +;============================================================================================================= +; END - Instructions Library +;============================================================================================================= + +;============================================================================================================= +; Interrupts +;============================================================================================================= +; BIOS + +; CX, DX Interval in microseconds +; CX : High, DX : Low +; SystemService +%define BIOS_Wait 0x86 + +; Disk + +; AL = Number of sectors to read (must be non-zero) +; CH = Track/Cylinder Number +; CL = Sector Number +; DH = Head Number +; DL = Drive Number +; ES:BX = Pointer to Buffer +%define Disk_ReadIntoMemory 0x02 + +; Disk Services (Storage) +%define DiskService 0x13 + +; Memory + +; Real Mode - Conventional Lower Memory +%define Mem_RM_CLower_Start 0x0500 +%define Mem_RM_CLower_End 0x7BFF +; 2 Byte Boundary Alignment +%define Mem_RM_CLower_2BB_End 0x7BE0 + +; Real Mode - Conventional Upper memory +%define Mem_RM_CUpper_Start 0x7E00 +%define Mem_RM_CUpper_End 0x7FFF +; 2 Byte Boundary Alignment +%define Mem_RM_CUpper_2BB_End 0x7FE0 + +; Real Mode - OS Boot Sector +%define Mem_BootSector_Start 0x7C00 +%define Mem_BootSector_512 0x7CFE +%define Mem_BootSector_End 0x7DFF + +; Misc System Services +%define SystemService 0x15 + +; Video +%define VideoService 0x10 + +; Returns +; AH = Number of character columns +; AL = Display mode +; BH = Active Page +%define Video_GetCurrentMode 0x0F + +; Used to set the video mode. +%define Video_SetMode 0x00 + +; SetVideoMode - Modes +; cbOff : Color Burst Off +%define VideoMode_Text_40x25_cbOff 0x00 +%define VideoMode_Text_40x25 0x01 +%define VideoMode_Text_80x25_cbOff 0x02 +%define VideoMode_Text_80x25 0x03 +%define VideoMode_Graphics_320x200 0x04 +%define VideoMode_Graphics_320x200_cboff 0x05 +%define VideoMode_Graphics_640x200 0x06 + +; Output a character +%define Video_TeleType 0xE +; Where memory buffer for Video's Text mode starts +%define Video_Text_MemBuffer 0xB800 +;============================================================================================================= +; END - Interrupts +;============================================================================================================= + + +%define char_CR 0xD ; Carriage Return +%define char_LF 0xA ; Line Feed + + +%define AAL_x86_Def +%endif + + diff --git a/Erus.boot.s b/Erus.boot.s new file mode 100644 index 0000000..84656d6 --- /dev/null +++ b/Erus.boot.s @@ -0,0 +1,79 @@ +; Print HEx + +; x86 +; 16-bit - Real Mode, V86 Mode + +; https://codereview.stackexchange.com/questions/230755/display-hexadecimal-value-stored-at-a-register + + +%include "AAL.x86.s" +%include "AAL.x86.routines.macros.s" + + +; 16-Bit Mode +[BITS 16] +; The ORG directive specifies the starting address of a segment +[ORG Mem_BootSector_Start] + + +start: + mov BX, Mem_BootSector_Start + + mov AH, BIOS_Wait + mov CX, 0x10 +int SystemService + +; Exclusive-OR (xor'ing a value to itself zeros the value) + xor AX, AX +; Set Data Segment and Extra Segment to 0x0000 + mov DS, AX + mov ES, AX +; Set Stack Segment (SS) to to 0x0000 + mov SS, AX +; Set Stack Pointer (SP) to the start of the boot sector. + mov SP, BX + + mov BX, Str_Erus + mov CX, 4 + push CX +call out_string + pop CX + + mov BX, Str_PostMsg + mov CX, 22 + push CX +call out_string + pop CX + + mov AH, BIOS_Wait + mov CX, 0x10 +int SystemService + + mov AH, Video_SetMode + mov AL, VideoMode_Text_80x25 +int VideoService + + mov BX, Str_Erus + mov CX, 4 + push CX +call out_string + pop CX + +; Idle +hang : +jmp short hang + +%include "AAL.x86.routines.s" + +; Data +Str_Erus: db 'Erus' +Str_PostMsg : db '... taking over boot', 0xA, 0xD + +;============================================================================================================= +; Wrap up +;============================================================================================================= +; Byte pad 512 bytes (zeroed) +times 510-$+start db 0 +; Master Boot Record signature +db 0x55 +db 0xAA diff --git a/bare_x86.code-workspace b/bare_x86.code-workspace new file mode 100644 index 0000000..5709732 --- /dev/null +++ b/bare_x86.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..2b2ffe2 --- /dev/null +++ b/readme.md @@ -0,0 +1 @@ +Assembly learning dump, nothing special