Reputation: 23
I am new to x86-16bit programming. I am very stumped by how I call function 2 properly to read characters individually from a string. If anybody has any ideas it would be greatly appreciated. The code below shows my current attempt (one of many).
.model small
.data
message db "Hello, DOS Here!", 0dh, 0ah
.code
main proc
mov ax, @data
mov ds, ax
L1:
mov ah, 2
mov bx, 1
int 21h
loop L1
.EXIT
main endp
end main
I'm also supposed to use push and pop to be able to print the string in the same method but backwards. I'm sure I'm missing something obvious. All I get when it prints is the British pound symbol for a few lines. (Dec: 156; Hex: 9C)
Upvotes: 1
Views: 6970
Reputation: 3851
Caveat: I haven't done this in decades and I don't have a compiler in front of me that can do this. This looks like an assignment so I'm not going to write the code, but I'll point you in the right direction.
Int 21h function 2 requires you to set dl
equal to the character you want to output. No pushes and pops required here since DOS doesn't use the stack for parameter passing. First, outside of your loop, you want to point a register to the address of the message, something like: MOV si, message
. Then, you need to dereference a single byte from the message and put it into dl
. This will require using indirect address notation. Then you can call interrupt 21h and write the character.
As for the loop, there are a few ways to approach it. You could use a counter, with cx
being the typical register for that, and use a LOOP
statement or DEC
and JNZ
statements. Or you could put a marker at the end of the string, and terminate the loop when you hit that marker. A null character is commonly used for this. You will also need to move to the next character in the string. You can do that by adding an index, or by incrementing the value of the si
register each iteration of the loop. Something like INC si
With all that said, there is a much easier way that avoids the loop but maybe it is cheating. Take a look at interrupt 21h function 9
Upvotes: 1
Reputation: 9899
With this definition message db "Hello, DOS Here!", 0dh, 0ah
, next code will print the complete message:
mov ah, 02h
mov dl, message ;Get the H character
int 21h
mov dl, message+1 ;Get the e character
int 21h
mov dl, message+2
int 21h
mov dl, message+3
int 21h
mov dl, message+4
int 21h
mov dl, message+5
int 21h
mov dl, message+6
int 21h
mov dl, message+7
int 21h
mov dl, message+8
int 21h
mov dl, message+9
int 21h
mov dl, message+10
int 21h
mov dl, message+11
int 21h
mov dl, message+12
int 21h
mov dl, message+13
int 21h
mov dl, message+14
int 21h
mov dl, message+15
int 21h
mov dl, message+16 ;Get the 0Dh carriage return
int 21h
mov dl, message+17 ;Get the 0Ah linefeed
int 21h
Rather stupid, wouldn't you say?
In order to use a loop and obtain much compacter code we need to:
SI
, DI
, BX
and BP
. I've picked BX
in below code.A version of this loop:
mov bx, OFFSET message ;1.
Again:
mov dl, [bx] ;2.
mov ah, 02h ;3.
int 21h
inc bx ;4.
cmp dl, 0Ah ;5.
jne Again
I'm also supposed to use push and pop to be able to print the string in the same method but backwards.
To accomplish this next task of yours, you would put a push dx
in between steps 2. and 3. Then write an additional loop to display the reversed string:
Again2:
pop dx
mov ah, 02h
int 21h
cmp dl, "H"
jne Again2
The pitfalls here will be that
pop
s before starting the 2nd looppush
sUpvotes: 1
Reputation: 23
Yeah, using function 9 would be 'cheating' as it is one of the other exercises (which was the easy one). I have revised my code and got it to start with the beginning character. I just need to figure out how to get it to keep looping so that it continues to read the string and not stop arbitrarily. Here's what I've got so far (It prints H and the 15 e's):
.model small
.data
message db "Hello, DOS Here!"
.code
main proc
mov ax, @data
mov ds, ax
mov ah, 2
mov cx, 16
mov dl, message
L1:
int 21h
mov dl, message + 1
loop L1
.EXIT
main endp
end main
Upvotes: 0