A while back, I posted a question involving code of the same function. This post contains improved code.
From the last post, I have improved size, my work with conventions, and my comments. I was also able to minimalism memory interaction to speed things up/make things more efficient.
%define KERNEL_CALL int 80h
%define STDOUT 1
%define SYS_WRITE 4
%define EXIT 1
%define NEWLINE 0xA
%define ASCII_NUM 30h
; @params: AX - a number that is converted to ASCII, then printed
; @return: no return
%macro put_num 0
push ax; push ax onto the stack(for restoring value)
add ax, ASCII_NUM; numerical to ascii
push ax; push ax onto the stack(for reference by ESP)
mov edx, 1; message length
mov ecx, esp; the number from the stack pointer
mov ebx, STDOUT
mov eax, SYS_WRITE
KERNEL_CALL; logs the number to the console
pop ax; getting it out of the way
pop ax; restoring the original value of ax
%endmacro
section .text
global _start; for gnu linker
_start:
push '10'; push '10' to the stack for reference by ESP
mov edx, 2; length
mov ecx, esp; message(number)
mov ebx, STDOUT
mov eax, SYS_WRITE
KERNEL_CALL; logs '10' to the console
mov ax, 9; initialize ax
countdown:
put_num; log the current number to stdout
.subtract:
sub ax, 1; subtract 1
cmp ax, 0; compare ax with 0...
je .blast_off; if equal, jump to .blast_off
jmp countdown; if not equal, go back to countdown
.blast_off:
mov edx, len; message length
mov ecx, msg; message
mov ebx, STDOUT
mov eax, SYS_WRITE
KERNEL_CALL; logs 'Blast off!' to the console
xor ebx, ebx
mov eax, EXIT
KERNEL_CALL; exit
section .data
msg db "Blast off!", NEWLINE
len equ $ - msg
Output (I know - the formatting still needs work):
10987654321Blast off!
Assembled: nasm -f elf bo7_working.s
Linked:: ld -m elf_i386 -s -o bo bo7_working.o
Some concerns:
- After I learned about macros, I started to use them a lot. Am I using them in place of headers (and is this bad), or is how I am using them fine?
- Am I over-using/misusing
%define
s (more specifically,KERNEL_CALL
)? - Do I have too many or too few comments?
- Are my comments unclear?
- Are there any unnecessary lines? I'm a little worried about the
pop
ping at the end ofput_num
... - Am I following convention, or are there more things I should do?
- Is my code understandable?
1 Answer 1
•After I learned about macros, I started to use them a lot. Am I using them in place of headers (and is this bad), or is how I am using them fine?
Looks OK to me.
•Am I over-using/misusing %defines (more specifically, KERNEL_CALL)?
I wouln't use KERNAL_CALL
in stead of int 80h
. The latter is shorter and the value involved will not change any soon in the future.
•Do I have too many or too few comments?
I find commenting on .subtract: a bit stating the obvious.
•Are my comments unclear?
No, they are very readable.
•Are there any unnecessary lines? I'm a little worried about the popping at the end of put_num...
The popping at the end of put_num is correct (pushing/popping 2 words in a row nicely keeps the stack aligned at dwords) but a few lines seem unnecessary to me. You do not need to compare AX with 0 since subtracting already defines the flags. You could also shave off an extra jump.
sub ax, 1; subtract 1
cmp ax, 0; compare ax with 0...
je .blast_off; if equal, jump to .blast_off
jmp countdown; if not equal, go back to countdown
.blast_off:
Better code:
sub ax,1
jnz countdown
.blast_off:
•Am I following convention, or are there more things I should do?
The ordering of the sections of the program is a matter of taste. But I see most people put the .data section before the .text section.
•Is my code understandable?
Very understandable.