%macro print_format 1 lea si, [%1] call _print_format %endmacro %macro print_format 2 lea si, [%1] push %2 call _print_format add sp, 2 %endmacro %macro print_format 3 lea si, [%1] push %3 push %2 call _print_format add sp, 4 %endmacro %macro print_format 4 lea si, [%1] push %4 push %3 push %2 call _print_format add sp, 6 %endmacro %macro print_format 5 lea si, [%1] push %5 push %4 push %3 push %2 call _print_format add sp, 8 %endmacro %macro print_format 6 lea si, [%1] push %6 push %5 push %4 push %3 push %2 call _print_format add sp, 10 %endmacro %macro print_format 7 lea si, [%1] push %7 push %6 push %5 push %4 push %3 push %2 call _print_format add sp, 12 %endmacro BITS 16 dumpmem_hardcoded_args: mov si, sp mov si, [si] mov cx, 400 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dumpmem: ; Dumps memory ; IN 'si': Start address to dump from ; IN 'cx': Number of bytes do dump ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; pusha xor edx, edx .loop: mov ax, word [esi + 2*edx] inc edx call dumpax mov ax, (0xE<<8)|' ' ; print space int 0x10 loop .loop .end: popa ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dumpax: ; Prints the contens of ax as a hexadecimal number ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; pusha ; save registers mov dx, ax mov ah, 0xE ; Teletype output mov cx, 4 ; 4 nibbles in a 16 bit word .print_loop: rol dx, 4 ; rotate to next nibble mov al, dl ; we copy to al because we need to mask only the low 4 bits and al, 0xF ; Do the masking add al, '0' ; convert to ASCII ; If we are greater than 9 ascii... cmp al, '9' jbe .skip_diff_to_ascii_A add al, 'A'-('9'+1) ; ...add 7 to make digits 10 to 15 be represented as 'A' to 'F' .skip_diff_to_ascii_A: int 0x10 ; BIOS call 'output' loop .print_loop popa ; restore registers ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dumpax10: ; Prints the contens of ax as a decimal number ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; pusha mov bx, 10 ; Divisor xor cx, cx ; Digit count starts at 0 .loop_divide: ; finds digits and pushes them to stack test ax, ax jz .break_loop_divide xor dx, dx div bx ; dx = (dx:ax)%bx, ax = (dx:ax)/bx push dx inc cx ; Increase digit count jmp .loop_divide .break_loop_divide: .loop_print: pop ax add al, '0' ; Convert to ascii mov ah, 0xE int 0x10 loop .loop_print popa ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dumpax_char: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov ah, 0xE int 0x10 ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; keyprint: ; Enters a loop where the keycode of each pressed key is printed ; [ESC] exits the loop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; pusha mov si, .f_info call print .keyprint_loop: mov ax, 0x1000 ; BIOS call to wait for key int 0x16 mov bx, ax ; Save KeyCode in bx print_format .f, ax, ax cmp bx, 0x011B ; ESC key je .break_keyprint_loop jmp .keyprint_loop .break_keyprint_loop: popa ret .f_info: db 13, 10, "Press keys to see their keycodes.",13,10,"Press [ESC] to exit.", 13, 10, 0 .f: db "(%c: %x)", 13, 10, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dump_stack_registers: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; push si print_format .format_string, sp, bp pop si ret .format_string: db "StackRegisters(SP:%x BP:%x)", 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dump_general_registers: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; push si print_format .format_string, ax, cx, dx, bx, si, di pop si ret .format_string: db "GeneralRegisters(ax:%x cx:%x dx:%x bx:%x si:%x di:%x)", 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dump_segment_registers: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; push si print_format .format_string, ss, cs, ds, es, fs, gs pop si ret .format_string: db "SegmentRegisters(Stack:%x Code:%x Data:%x Extra:%x F:%x G:%x)", 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _print_format: ; IN: variable number of 16-bit numbers on stack ; IN: 'si' points to beginning of format string with the following format: ; %x in string replaced with hexadecimal representation ; %d in string replaced with decimal representation ; %% in string replaced with literal % sign ; ; EXAMPLE call: ; push word 1337 ; push word 0xbeef ; push word 0xdead ; lea si, [.FORMAT] ; call print_format ; output: "(DEAD-BEEF){1337} 100%" ; add sp, 6 ; (...) ; .FORMAT: db "(%x-%x){%d} 100%%",0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; push bp mov bp, sp pushf pusha lea bp, [bp+4] .outer_loop: mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function .print_loop: lodsb ; al = *si++ cmp al, '%' je .break_print test al, al jz .break_outer int 0x10 jmp .print_loop .break_print: lodsb cmp al, 'x' je .format_hex cmp al, 'd' je .format_dec cmp al, 'c' je .format_char cmp al, '%' je .print_literal_percent .format_hex: lea cx, [dumpax] jmp .print_ax .format_dec: lea cx, [dumpax10] jmp .print_ax .format_char: lea cx, [dumpax_char] .print_ax: mov ax, [bp] lea bp, [bp+2] call cx jmp .outer_loop .print_literal_percent: mov ax, (0xE<<8)|'%' int 0x10 jmp .outer_loop .break_outer: popa popf pop bp ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dump_dx_as_two_chars: ; IN dh: first char ; IN dl: second char ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; push ax mov ah, 0xE mov al, dh int 0x10 mov al, dl int 0x10 pop ax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dump_status_flags: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; pushf push si push ax push bx lahf mov bl, ah lea si, [.flags_string] mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function .outer_loop: ; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)] .print_loop: lodsb ; Load byte at address SI into AL, and increment SI cmp al, '%' je .break_print_loop ; If the character is zero (NUL), stop writing the string test al, al jz .break_outer_loop int 0x10 ; Otherwise, print the character via 'int 0x10' jmp .print_loop ; Repeat for the next character .break_print_loop: ror bl, 1 mov al, bl and al, 1 add al, '0' int 0x10 jmp .outer_loop .break_outer_loop: pop bx pop ax pop si popf ret .flags_string: db "Flags(Sign:% Zero:% ?:% Adjust:% ?:% Parity:% ?:% Carry:%)", 0