Last active
October 14, 2020 10:24
-
-
Save vmxdev/075d1015abc2ff05b7236c2486787d85 to your computer and use it in GitHub Desktop.
fizzbuzz in GNU assembly
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
/* | |
* To compile and link: | |
* | |
* $ gcc -Wall -pedantic -Wextra fizzbuzz.s -no-pie -o fizzbuzz | |
*/ | |
.data | |
/* Strings to print */ | |
fizz: .asciz "fizz\n" | |
.equ fizz_len, . - fizz - 1 | |
buzz: .asciz "buzz\n" | |
.equ buzz_len, . - buzz - 1 | |
fizzbuzz: .asciz "fizzbuzz\n" | |
.equ fizzbuzz_len, . - fizzbuzz - 1 | |
/* Format string for printf(), we will print number with it */ | |
format: .asciz "%d\n" | |
.align 2 | |
/* Loop counter with initial value */ | |
i: .word 1 | |
/* And loop limit */ | |
.equ limit, 100 + 1 | |
.text | |
/* Helper macros */ | |
/* Print string (using write() syscall) if (i mod DIVISOR) == 0 */ | |
.macro PRINT_STR_OR_CONTINUE DIVISOR, MSG, LEN | |
mov \DIVISOR, %rcx | |
movl i(%eip), %eax | |
xor %rdx, %rdx | |
div %rcx | |
/* check modulo */ | |
or %rdx, %rdx | |
/* if not zero, jump to end of macro */ | |
jnz 1f | |
/* else print string */ | |
mov $1, %rax | |
mov $1, %rdi | |
mov \MSG, %rsi | |
mov \LEN, %rdx | |
syscall | |
/* and jump to next loop iteration */ | |
jmp END_DO | |
1: | |
.endm | |
/* Print integer number using printf(format, i); format is "%d\n" */ | |
.macro PRINT_NUMBER X | |
push %rbx | |
lea format(%rip), %rdi | |
xor %eax, %eax | |
mov \X, %esi | |
call printf | |
pop %rbx | |
.endm | |
/* Increment I and jump to DO if (I != LIMIT) */ | |
.macro WHILE I, LIMIT | |
mov \I, %eax | |
inc %eax | |
mov %eax, i(%eip) | |
cmp \LIMIT, %eax | |
jne DO | |
.endm | |
/* Exit with return code "CODE" */ | |
.macro EXIT CODE | |
movq $60, %rax | |
movq \CODE, %rdi | |
syscall | |
.endm | |
.globl main | |
.type main, @function | |
main: | |
/* entry point */ | |
DO: | |
PRINT_STR_OR_CONTINUE $(3 * 5), $fizzbuzz, $fizzbuzz_len | |
PRINT_STR_OR_CONTINUE $3, $fizz, $fizz_len | |
PRINT_STR_OR_CONTINUE $5, $buzz, $buzz_len | |
PRINT_NUMBER i(%eip) | |
END_DO: | |
WHILE i(%eip), $limit | |
EXIT $0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment