Logo  

CS456 - Systems Programming

Displaying exercises/e5/solution/pyramid.s

%include "lib/lib.h"

extern puts, putc

SECTION .data
  usage: db `Usage: pyramid <height>\n`,0
  error: db `height must be positive.\n`,0

SECTION .text
atol:					;long atol(char *rsi) {
	MOV	rax, 0			;  int rax = 0, rbx = 10, r13;
	MOV	r13, 0
	MOV	rbx, 10
.loop	CMP	BYTE [rsi], 0
	JE	.done			;  while(*rsi != '\0') {
	CQO
	MUL	rbx			;    rax *= rbx;
	MOV	r13b, BYTE [rsi]
	SUB	r13, '0'		;    r13 = *rsi - '0';
	ADD	rax, r13		;    rax += r13;
	INC	rsi			;    rsi++;
	JMP 	.loop			;  }
.done	RET				;  return rax;


global _start
_start:
	mov	rax, [rsp]		; if (argc < 2) {
	cmp	rax, 2
	jge	.getnum

	mov	rsi, usage		
	call	puts			;   printf("Usage: pyramid <height>\n");
	mov	rax, SYS_EXIT		;   return 0;
	mov	rdi, 0
	syscall				; }

.getnum:
	mov	rsi, [rsp+16]
	call	atol
	mov	r15, rax		; h(r15) = atol(argv[1]);

	cmp	r15, 0			; if (h <= 0) {
	jg	.pyramid

	mov	rsi, error		;     printf("height must be positive.\n");
	call	puts
	mov	rax, SYS_EXIT		;     return 1;
	mov	rdi, 1
	syscall				; }

.pyramid:
	mov	r14, r15
	dec	r14			; s = h-1
	mov	r13, 1			; a = 1

	mov 	r12, 0			; i = 0

.mainloop:
	cmp	r12, r15		; while(i < h) {
	je	.done  

	mov	rbx, 0			;    for(j = 0; j < s; j++) putchar(' ');
.loop1:
	cmp	rbx, r14
	je	.endloop1

	mov	rax, ' '
	call	putc
	
	inc	rbx
	jmp	.loop1
.endloop1:

	mov	rbx, 0			;    for(j = 0; j < a; j++) putchar(' ');
.loop2:
	cmp	rbx, r13
	je	.endloop2

	mov	rax, '*'
	call	putc

	inc	rbx
	jmp	.loop2
.endloop2:

	mov	rax, `\n`		;   putchar('\n');
	call	putc

	dec	r14			;   s--;
	add	r13, 2			;   a += 2;

	inc	r12			;   i++;
	jmp	.mainloop
.done:					; }

	mov	rax, SYS_EXIT		; return 0;
	mov	rdi, 0
	syscall