Skip to content

Instantly share code, notes, and snippets.

@nkmathew
Last active August 29, 2015 13:56
Show Gist options
  • Save nkmathew/9168655 to your computer and use it in GitHub Desktop.
Save nkmathew/9168655 to your computer and use it in GitHub Desktop.
An assembly(NASM) program that prints a diamond pattern
;; @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