Last active
September 12, 2018 05:03
-
-
Save winny-/806a4db81d58748d01be to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
org 0x100 | |
movzx cx, [0x80] | |
mov bx, 1 ; stdout | |
mov dx, 0x81 | |
mov ah, 0x40 | |
int 0x21 | |
mov ax, 0x4c00 | |
int 0x21 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%macro WriteString 1 | |
mov ah, 0x9 ; the "syscall" number | |
mov dx, %1 ; offset of the string, '$' terminated. | |
int 0x21 ; Call into DOS. | |
%endmacro | |
%macro Exit 1 | |
mov ah, 0x4c ; the "syscall number" | |
mov al, %1 ; exit number, 0 = success. | |
int 0x21 | |
%endmacro | |
; COM file starts at 0x100, the space before is used at runtime to set | |
; initial program state. | |
org 0x100 | |
Start: | |
mov ax, 0x82 ; First char [0x81] is always a separator. | |
movzx cx, [0x80] ; Length of args string. | |
dec cx ; Account skipping 0x81. | |
call IsDigit | |
cmp ax, 0 ; Is our arg not digits? | |
jz .B1 | |
WriteString haveDigits | |
mov ax, 0x82 ; First char [0x81] is always a separator. | |
movzx cx, [0x80] ; Length of the arguments string. | |
dec cx ; Account for skipping the first character. | |
call StringToInt | |
jmp .B2 | |
.B1: | |
mov ax, [nummax] ; Otherwise set a sensible default. | |
.B2: | |
call FizzBuzz | |
Exit 0 | |
nop ; Padding for readibility when debugging. | |
nop | |
haveDigits db 'Have digits',0xa,0xd,'$' | |
nummax dw 15 | |
nop | |
nop | |
; Inputs: AX -- number to count up to | |
; Outputs: None. | |
; Writes to console. | |
FizzBuzz: | |
pusha | |
mov bp, sp | |
sub sp, 6 ; Reserve 6 bytes for local data. | |
mov bx, ax ; Copy num to count up to into bx. | |
mov cx, 1 ; Start at 1. | |
.L1: | |
xor si, si ; Using si as a flag, clear at start of loop. | |
mov ax, cx ; Set dividend. | |
xor dx, dx ; Clear upper half of dividend. | |
mov di, 3 ; Set divisor. | |
div di | |
cmp dx, 0 ; Is there a remainder? | |
jne .B1 | |
inc si | |
WriteString fizzstr | |
.B1: | |
mov ax, cx | |
xor dx, dx | |
mov di, 5 | |
div di | |
cmp dx, 0 ; Is there a remainder? | |
jne .B2 | |
inc si | |
WriteString buzzstr | |
.B2: | |
cmp si, 0 ; Is si set?, then print the number. | |
jne .B3 | |
mov ax, cx | |
push bx | |
lea bx, [bp-6] ; Load the address of local buffer. | |
call IntToString | |
WriteString bx | |
pop bx | |
.B3: | |
WriteString sepstr | |
inc cx | |
cmp cx, bx ; Are we still counting up? | |
jbe .L1 | |
add sp, 6 ; Dismiss our local data. | |
popa | |
ret | |
nop | |
nop | |
fizzstr db 'Fizz','$' | |
buzzstr db 'Buzz','$' | |
sepstr db 0xa,0xd,'$' | |
nop | |
nop | |
; Inputs: AX -- the integer, BX -- the output string address | |
; Outputs: None. | |
; Assumes the output is wide enough for a 16-bit integer. | |
; | |
; May be a bit slow because it copies the string digits in a temp | |
; buffer, and then copies the temp buffer into [bx] in reverse. | |
; This way this code doesn't need to know in advance how many digits | |
; are in the output string. | |
IntToString: | |
pusha | |
mov bp, sp | |
sub sp, 5 ; Reserve 5 bytes for a buffer. | |
; Convert to base 10 and turn each digit into an ascii digit. | |
lea si, [bp-5] ; Load the address of buffer. | |
mov cx, si ; Copy into cx. | |
mov di, 10 ; Set the divisor only once. | |
.L1: | |
xor dx, dx ; Clear upper half of dividend. | |
div di | |
add dl, '0' ; Add constant '0' to the remainder. | |
mov [si], dl ; Copy into our buffer. | |
cmp ax, 0 ; Finished converting to base 10? | |
je .B1 | |
inc si | |
jmp .L1 | |
; Copy buffer in reverse order and add a '$'. | |
.B1: | |
.L2: | |
mov al, byte [si] | |
mov [bx], byte al | |
dec si | |
inc bx | |
cmp si, cx | |
jae .L2 | |
mov [bx], byte '$' | |
add sp, 5 | |
popa | |
ret | |
nop | |
nop | |
; Inputs: AX -- address of the string, CX -- number of bytes in string. | |
; Outputs: AX = 0 if not all bytes are ascii digits. | |
IsDigit: | |
push bx | |
push cx | |
mov bx, ax | |
.L1: | |
cmp [bx], byte '0' | |
jb .B2 | |
cmp [bx], byte '9' | |
ja .B2 | |
inc bx | |
loop .L1 | |
.B1: | |
mov ax, 1 | |
jmp .END | |
.B2: | |
xor ax, ax | |
.END: | |
pop cx | |
pop bx | |
ret | |
nop | |
nop | |
; Inputs: AX -- the string, CX -- the length of the string | |
; Outputs: AX -- the integer | |
StringToInt: | |
push bx | |
push cx | |
push di | |
push si | |
mov bx, ax | |
xor ax, ax | |
mov si, 10 | |
.L1: | |
movzx di, byte [bx] | |
sub di, '0' | |
mul si | |
add ax, di | |
inc bx | |
loop .L1 | |
pop si | |
pop di | |
pop cx | |
pop bx | |
ret | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
org 0x100 | |
call sayhello | |
mov ax, winston | |
call greetname | |
call sayhello | |
mov ax, 0x4c00 ; ah = 0x4c (exit), al = 0x00 (success) | |
int 0x21 | |
sayhello: | |
push ax | |
push dx | |
mov dx, hellostr | |
mov ah, 9 | |
int 0x21 | |
pop dx | |
pop ax | |
ret | |
greetname: | |
nameptr dw 0 | |
push ax | |
push dx | |
mov [nameptr], ax | |
mov ah, 9 | |
mov dx, hi | |
int 0x21 | |
mov ah, 9 | |
mov dx, [nameptr] | |
int 0x21 | |
mov ah, 9 | |
mov dx, crlf | |
int 0x21 | |
pop dx | |
pop ax | |
ret | |
hellostr db 'Hello, world!',0xd,0xa,'$' | |
winston db 'Winston','$' | |
hi db 'Hi, ','$' | |
crlf db 0xd,0xa,'$' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
org 0x100 | |
xor dl, dl | |
mov si, buf2 | |
mov ah, 0x47 | |
int 0x21 | |
xor al, al | |
mov di, buf2 | |
cld | |
repnz scasb | |
mov [di-1], byte '$' | |
mov ah, 0x19 | |
int 0x21 | |
add al, 'A' | |
mov [buf], byte al | |
mov dx, buf | |
mov ah, 0x9 | |
int 0x21 | |
mov ax, 0x4c00 | |
int 0x21 | |
nop | |
nop | |
buf db 0,':\' | |
buf2 resb 64 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment