Yeah! That jumps around a bit less (generally a good thing).
Shikatsu used ecx - not really necessary here, but it illustrates that we can use 32-bit registers, even 32-bit addressing modes, in 16-bit code. There's a slight "penalty" for using 32-bit registers in 16-bit code (or using 16-bit registers in 32-bit code): Nasm inserts a "operation size override prefix", the byte 66h, (67h is the "address size override prefix") into your code. Doesn't gain you much here, but in some cases it is well worth the "cost" to do it. Especially the 32-bit addressing modes!
The "trick" is that "mov cx" and "mov ecx" are the same opcode. You can see this in the disassembly...
00000000 B90500 mov cx,0x5
00000003 66B905000000 mov ecx,0x5
Note that, besides the 66h override, the integer 5 now takes up 4 bytes instead of just two. This is why you can't run 16-bit code when the CPU is in 32-bit mode (and vise-versa).
Anyway, either will work. I just noticed that you've got your "print" subroutine in "segment .data". That won't do any harm, but all your code should be in "segment .text". Doing the printing inline, as Alfonso shows, is simpler if you're only calling if from one place (even if in a loop), but it's good to learn to write a subroutine, so that it can be called from many places. The problem with this "print" subroutine, for that purpose, is that it always prints the same thing. A more "reusable" subroutine would print something passed as a parameter. Since we want the thing to print in dl, the very simplest "calling convention" (if you can even call it that) would be to pass the parameter in dl...
; To compile nasm code type:
; nasm myprog.asm -fbin -o myprog.com (or myprog.exe)
org 100h
segment .text
mov ECX, 5
mov byte [var], 30h
label1:
dec ECX
jz label2
add byte [var], 1h
mov DL, [var]
call print
jmp label1
label2:
mov dl, 'h'
call print
exit:
mov AX, 0;4C00h
int 21h
segment .bss
var RESB 1
segment .text
; print - prints a character
; expects - character to print in dl
; returns - nothing useful
; clobbered - ax
print:
mov ah, 2h
int 21h
ret
Of course... it doesn't use "jnz" anymore...
I notice you've commented out 4C00h and replaced it with 0 in the exit. Trouble with 4C00h, or were you just experimenting? Another way to exit is just "ret". This works (in a .com file!) because dos has pushed a zero to the stack when loading us. When the "ret" gets its return address from the stack, it jump to location zero (in our one-and-only segment), where dos has thoughtfully put "int 20h" - CD 20 - still another way to exit. Make sure that you DO exit cleanly, one way or another, or the CPU will keep executing (or trying to) whatever bytes it finds next. This probably won't be a command to format your hard drive, but don't take chances.
Best,
Frank