Last active
August 29, 2015 13:56
-
-
Save nkmathew/9168655 to your computer and use it in GitHub Desktop.
An assembly(NASM) program that prints a diamond pattern
This file contains 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
;; @started: 19th February 2014 20:30 | |
;; @completed: 23rd February 2014 11:20 | |
;; Original C program | |
;; #include <stdio.h> | |
;; | |
;; void print_diamond(int width) { | |
;; /* | |
;; ** Every level is has two less or more characters than the next. | |
;; ** No of characters per line: | |
;; n*2-1 if width is odd | |
;; n*2-2 if width is even except the first and last | |
;; width=height | |
;; */ | |
;; int middle = width / 2; | |
;; int height = width; | |
;; int y, x, trend = 0, characters = 1, chars; | |
;; for (y = 0; y <= height; y++) { | |
;; chars = 0; | |
;; for (x = 0; x <= width; x++) { | |
;; if (x >= middle && chars < characters) { | |
;; printf("*"); | |
;; chars++; | |
;; } else { | |
;; printf(" "); | |
;; } | |
;; } | |
;; | |
;; if (middle == 0) { | |
;; trend = 1; | |
;; } | |
;; printf("\n"); | |
;; if (trend == 0) { | |
;; middle--; | |
;; characters += 2; | |
;; } else { | |
;; middle++; | |
;; characters -= 2; | |
;; } | |
;; } | |
;; } | |
;; | |
;; int main() { | |
;; print_diamond(10); | |
;; return 0; | |
;; } | |
;; | |
;; Compiling: | |
;; nasm -f win32 nasm-print-diamond.asm | |
;; gcc nasm-print-diamond.obj -o diamond.exe | |
;; The program prints a diamond pattern like this: | |
;; The size of the diamond depends on constant WIDTH | |
;; All variables are stored on the stack and moved to register | |
;; EBX during comparisons. It's about the only register used. | |
;; The program is a translation of the C program above | |
;; * | |
;; *** | |
;; ***** | |
;; ******* | |
;; ********* | |
;; *********** | |
;; ********* | |
;; ******* | |
;; ***** | |
;; *** | |
;; * | |
;; 10 x 10 | |
;; ~~~~~~~~[ CONSTANTS ]~~~~~~~~~~~~~ | |
segment .data | |
EMPTY_STRING db "", 0 | |
ASTERISK db "*",0 | |
NEWLINE db 10,0 | |
SPACE db " ",0 | |
PROMPT db "Val: %ld",10,0 | |
PROMPT1 db "%ld",0 | |
RUNNING db "Loop still running...",10,0 | |
WIDTH equ 70 | |
MIDDLE equ WIDTH / 2 | |
HEIGHT equ WIDTH | |
CHARACTERS equ 1 | |
CHARS equ 0 | |
TREND equ 0 | |
X equ 0 | |
Y equ 0 | |
;;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
segment .text | |
global _main | |
extern _puts, _printf | |
;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
%macro print_char 1 | |
push %1 | |
call _printf | |
add ESP, 4 | |
%endmacro | |
%macro print_number 1 | |
;; Used for debugging | |
push %1 | |
push PROMPT1 | |
call _printf | |
add ESP, 8 | |
%endmacro | |
_main: | |
;; Allocate space for 8 'local' variables | |
sub ESP, 32 | |
mov dword [ESP], X | |
mov dword [ESP+4], Y | |
mov dword [ESP+8], HEIGHT | |
;; MIDDLE - Offset at which asterisks start getting printed | |
mov dword [ESP+12], WIDTH | |
;; CHARACTERS - Number of asterisks to be printed in the line | |
mov dword [ESP+16], CHARACTERS | |
mov dword [ESP+24], TREND | |
mov dword [ESP+28], MIDDLE | |
inc dword [ESP] | |
iterate_lines: | |
;; CHARS - Counts up to `CHARACTERS` | |
;; Placed here because it has to be reset in each iteration | |
mov dword [ESP+20], CHARS ;; CHARS = 0 | |
mov dword [ESP], X ;; X = 0 | |
iterate_characters: | |
;; Loop while characters is less than width | |
mov EBX, [ESP+28] ;; EBX = MIDDLE | |
cmp EBX, [ESP] ;; is EBX < MIDDLE?? | |
jg print_space ;; | |
mov EBX, [ESP+20] ;; EBX = CHARACTERS | |
cmp EBX, [ESP+16] ;; is CHARS > CHARACTERS?? | |
jge print_space | |
print_char ASTERISK ;; printf("*") | |
inc dword [ESP+20] ;; CHARS++ | |
jmp outside_if_statement ;; jump to avoid printing an asterisk | |
print_space: | |
print_char SPACE ;; printf(" ") | |
outside_if_statement: | |
;; ~~~~~~~[ iterate_characters loop ]~~~~~~~~~~~~~~ | |
inc dword [ESP] ;; X = X + 1 | |
mov EBX, [ESP] ;; EBX = X | |
cmp EBX, [ESP+12] ;; Y <= WIDTH | |
jle iterate_characters ;; LOOP | |
;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
mov dword EBX, [ESP+28] ;; EBX = MIDDLE | |
test EBX, EBX ;; is MIDDLE == 0?? | |
jnz middle_is_not_zero | |
mov dword [ESP+24], 1 ;; TREND = 1 | |
middle_is_not_zero: | |
print_char NEWLINE ;; printf("\n") | |
mov EBX, [ESP+24] ;; EBX = TREND | |
test EBX, EBX ;; is EBX == 0?? | |
jnz trend_is_not_zero | |
dec dword [ESP+28] ;; MIDDLE-- | |
inc dword [ESP+16] ;; CHARACTERS++ | |
inc dword [ESP+16] ;; CHARACTERS++ | |
jmp outside_trend_if_statement | |
trend_is_not_zero: | |
inc dword [ESP+28] ;; MIDDLE++ | |
dec dword [ESP+16] ;; CHARACTERS-- | |
dec dword [ESP+16] ;; CHARACTERS-- | |
outside_trend_if_statement: | |
;; ~~~~~~~[ iterate_lines loop ]~~~~~~~~~~~~~~ | |
inc dword [ESP+4] ;; Y = Y + 1 | |
mov EBX, [ESP+4] ;; EBX = Y | |
cmp EBX, [ESP+8] ;; is Y <= HEIGHT?? | |
jle iterate_lines ;; Loop to the next line | |
;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
exit_program: | |
;; Delete all 8 'local' variables and return | |
add ESP, 32 | |
ret | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment