Assembler (TASM x64) arrays and elements - windows

I have an array of nine names:
.model tiny
.data
vardas1 db "Rokas",0ah,'$'
vardas2 db "Tomas",0ah,'$'
vardas3 db "Matas",0ah,'$'
vardas4 db "Domas",0ah,'$'
vardas5 db "Augis",0ah,'$'
vardas6 db "Vofka",0ah,'$'
vardas7 db "Marka",0ah,'$'
vardas8 db "Auris",0ah,'$'
vardas9 db "Edvis",0ah,'$'
vardai dw offset vardas1, offset vardas2, offset vardas3, offset vardas4, offset vardas5, offset vardas6, offset vardas7, offset vardas8, offset vardas9
.code
org 100h
I need to read a digit from keyboard, and then I need to print that name. For example I will push 5, and console should write "Augis". BTW, second code block aren't all code, just loop that doesn't work
paieska:
mov dx, offset _comment1 ; Just string name asking user to input digit
mov ah, 9
int 21h
mov j, 00h ; Trying to input the digit from keyboard
mov ah, 01h
mov dl, 0ah
int 21h
mov bx, offset vardai ; Add array "names" to bx register
add bx, cx ; Add cx for indexing
mov dx, [bx] ; Add first array element to dx register
add cx, 2 ; Increasing cx by 2, because I'm using data word not data byte
mov ah, 9 ; Try to print it
int 21h
cmp cx, j ; Try to compare cx (index of array) to mine inputed digit "j"
jne paieska
je end

mov ah, 01h
mov dl, 0ah ;NO NEED FOR THIS - INT21/01 DOES NOT USE DL
int 21h
MOV AH, '1' ; MIN INPUT CHAR
mov bx, offset vardai ; Add array "names" to bx register WELL, ASSIGN ACTUALLY
MOV CX,2 ;NUMBER OF BYTES TO ADD (WORDS, NOT BYTES)
LOOPN:
mov dx, [bx] ; name-pointer array element to dx register
CMP AH,AL ; MATCHING char?
JE PNAME ; YES, PRINT NAME
add bx, cx ; Add cx=2 for next name
inc AH ; next possible character input
CMP AH,'9'+1 ; allowed is '1'..'9'
jne loopn ; in allowed range
; input not 1..9
mov dx, offset errormessage
PNAME:
mov ah, 9 ; Try to print it
int 21h
jmp end
Well, I tried to edit your approach with CAPS, but it became too complicated.
Essentially, you are reading a character from the keyboard using function 01. This character arrives in AL. If all goes well, it should be '1'..'9'. Notice these are the ASCII characters '1'..'9', that is hex 31..39
Next step is to set BX to the start of the table, AH to the minimum character you anticipate and CX to 2 because the table contains words, not bytes.
Now we have a loop. Load X from the table, and check whether AL is equal to AH. If the user input 1, these will be equal, so go print the string.
Otherwise, add 2 to BX to point to the next entry in the table (this could have been done by ADD BX,2 or INC BX INC BX which would mean the MOV CX,2 would be unnecessary - just the way I wrote it...) and increment the '1' in AH to '2'.
The end-condition for the loop is when AH gets incremented from '9' to - well, ':' or '9'+1. If it hasn't reached that end-condition, then run around the loop until all of the values '1'..'9' have been tested. If you haven't got to PNAME yet, then there's an error because the character input wasn't allowed, so point to an error message and then print it.
Now jumping to the end - probably you'd want to terminate the program, so you'd execute
MOV AH,4CH
INT 21H

Related

How to print an integer stored in a variable

So I have a program in 8086 assembly that allows the user to enter 2 digits, store them in a variable and then print out the number:
data segment
broj db ?
ends
stack segment
dw 128 dup(0)
ends
code segment
mov ax, data
mov ds, ax
mov es, ax
mov ah, 1h
int 21h
sub al, 48d
mov bl, 10d
mul bl
mov broj, al
mov ah, 1h
int 21h
sub al, 48d
add broj, al
mov dl, broj
sub dl, 48d
mov ah, 2h
int 21h
mov ax, 4c00h
int 21h
ends
However whenever I enter a number for example 21 it doesn't give me the number instead it gives me ASCII Code for that value.
Can anyone help?!
However whenever I enter a number for example 21 it doesn't give me the number instead it gives me ASCII Code for that value.
If you feed (input) your program a number that consists of 2 digits, then you'll have to print also 2 digits! Currently your code contains just the one character output function.
First divide the number in broj by 10 giving a quotient (in AL) and a remainder (in AH).
Convert the quotient to character (Add 48) and print it.
Convert the remainder to character (Add 48) and print it.
Example:
mov al, broj
mov ah, 0
mov bl, 10
div bl
add ax, "00"
mov dx, ax
mov ah, 02h
int 21h
mov dl, dh
mov ah, 02h
int 21h

Printing individual characters from a string to standard output in ms-dos/assembly x86-16

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)
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:
Put the address of your message in an address register. You can choose from SI, DI, BX and BP. I've picked BX in below code.
Read one byte at this address.
Output the byte with DOS.
Increment the pointer in the address register.
Repeat steps 2, 3, 4, 5 for all the text by checking if it was the linefeed character that you just outputted. Since in your text that's the very last character.
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
you shouldn't output the linefeed and carriage return before the other (real) characters ==> Hint: do 2 pops before starting the 2nd loop
you can't readily assume that "H" will only appear as the text's first character ==> Hint: count the number of pushs
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
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

Why does the following 8086 assembly code only display numbers up to 2559?

What am I trying to do ?
I want to get a 16-bit number from the user and print It on the console.
What Is the problem ?
Well my code works fine If the number entered Is less than 2600 but the moment I enter 2600 It displays "40" and for 2601 "41" and so on. Shouldn't It display numbers up to 65535 ? Because I am storing the value In the bx register which Is 16-bit and which can store at most 65535. Then why only 2559 ?
My code:
.model small
.data
msg db 10,13,'Enter a 16bit number: $'
newline db 10,13,'$'
.code
main:
mov ax, #data
mov ds, ax
mov cl, 10
mov bx, 0
mov ah, 09h
lea dx, msg
int 21h
call get16bitNum
mov ah, 09h
lea dx, newline
int 21h
mov ax, '$'
push ax
mov ax, bx
store:
div cl
cmp al, 0
mov bh, 0
mov bl, ah
push bx
je continue
mov ah, 0
jmp store
continue:
pop ax
cmp ax, '$'
je ext
mov bx, ax
mov ah, 02h
mov dx, bx
add dx, 48
int 21h
jmp continue
ext:
mov ah, 04ch
int 21h
proc get16bitNum
aggregate:
mov ah, 01h
int 21h
cmp al, 13
je return
mov ah, 0
sub al, 48
mov dx, bx
mov bx, ax
mov ax, dx
mul cl
add bx,ax
jmp aggregate
return:
ret
endp
end main
You don't actually retrieve a 16-bit number!
You keep the desired input in BX, and so you need to multiply the whole of BX by 10. You do this using a word sized multiplication.
proc get16bitNum
aggregate:
mov ah, 01h
int 21h
cmp al, 13
je return
mov ah, 0
sub al, 48 ;AX is 0 to 9
xchg ax, bx ;New digit temporarily in BX
mov cx, 10
mul cx ;Product is in DX:AX, but we won't use DX!
add bx ,ax ;Add new digit
jmp aggregate
return:
ret
You don't display the 16-bit number
The procedure to convert the number into text will definitely need to use the word sized division.
For an excellent explanation on how to do this see this recent post Displaying numbers with DOS. It explains in great detail everything you need to know about converting numbers. It even uses the same technique of pushing some value in the stack (You used a $ character for this) to know where the number ends.
ps. If you find the info in the linked post useful don't hesitate to upvote it. (Of course I hope you find my answer useful too!)
8 bit div produces 8 bit quotient and remainder.
When you divide 2600 by 10 you get an 8 bit quotient, losing higher bits.
You should use 16 bit division.

Converting quaternary to octal. ASM 8086

I have to prepare program for 8086 processor which converts quaternary to octal number.
My idea:
Multiplying every digit by exponents of 4 and add to register. Later check the highest exponent of 8 not higher than sum from first step.
Divide by exponents of 8 until remainder equals 0. Every result of dividing is one digit in octal.
But for 16-digits number last exponent of 4 is 4^15. I suppose It isn't optimal algorithm.
Is there any other way? Maybe to binary and group by 3 digits.
Turns out you can indeed process values 3 digits at a time. Done this way, you can process strings of arbitrary length, without being limited by the size of a register. Not sure why you might need to, unless aliens try to communicate with us using ascii strings of quaternary digits with huge lengths. Might happen.
It's possible to do the translation either way (Right to Left or Left to Right). However, there's a bit of a challenge to either:
If you are processing RtL, you need to know the length of the output string before you start (so that you know where to write the digits as you compute them). This is do-able, but a bit tricky. In simplest terms, the length is ((strlen(Q) + 2) / 3) * 2. That almost gets it. However, you can end up with a blank space at the beginning for a number of cases. "1" as well as "10" will give the blank space. "20" won't. The correct value can be computed, but it's annoying.
Likewise, processing LtR has a similar problem. You don't have the problem of figuring out where to write digits, but consider: If the string to convert it "123", then the conversion is simple (33 octal). But what if you start processing, and the complete string is "1231" (155 octal)? In that case what you need to process it like "001231" (01 55). IOW, digits can be processed in groups of 3, but you need to handle the initial case where the number of digits doesn't evenly divide by 3.
Posting solutions to homework is usually something I avoid. However I doubt you are going to turn this in as your 'solution,' and it's (barely) possible that google might send someone here who needs something similar.
A few things to note:
This code is intended to be called from C using Microsoft's fastcall (it made testing easier) and compiled with masm.
While it is written in 32bit (my environment), there's nothing that particularly requires 32bit in it. Since you said you were targeting 8086, I've tried to avoid any 'advanced' instructions. Converting to 16bit or even 64bit should not present much of a challenge.
It processes from left to right.
As with any well-written routine, it validates its parameters. It outputs a zero length string on error, such as invalid digits in the input string.
It will crash if the output buffer is NULL. I suppose I could return a bool on error (currently returns void), but, well, I didn't.
I'm sure the code could be tighter (couldn't it always?), but for "homework project quality," it seems reasonable.
Other than that, that comments should explain the code.
.386
.model flat
.code
; Call from C via:
; extern "C" void __fastcall PrintOct(const char *pQuat, char *pOct);
; On Entry:
; ecx: pQuat
; edx: pOct
; On Exit:
; eax, ecx, edx clobbered
; all others preserved
; If pOct is zero bytes long, an error occurred (probably invalid digits)
#PrintOct#8 PROC
; -----------------------
; If pOct is NULL, there's nothing we can do
test edx, edx
jz Failed
; -----------------------
; Save the registers we modify (except for
; eax, edx and ecx which we treat as scratch).
push esi
push ebx
push edi
mov esi, ecx
mov edi, edx
xor ebx, ebx
; -----------------------
; esi: pQuat
; edi: pOct
; ebx: zero (because we use lea)
; ecx: temp pointer to pQuat
; Reject NULL pQuat
test esi, esi
jz WriteNull
; -----------------------
; Reject 0 length pQuat
mov bl, BYTE PTR [esi]
test bl, bl
jz WriteNull
; -----------------------
; How many chars in pQuat?
mov dl, bl ; bl is first digit as ascii. Preserve it.
CountLoop:
inc ecx ; One more valid char
; While we're counting, check for invalid digits
cmp dl, '0'
jl WriteNull
cmp dl, '3'
jg WriteNull
mov dl, BYTE PTR [ecx] ; Read the next char
test dl, dl ; End of string?
jnz CountLoop
sub ecx, esi
; -----------------------
; At this point, there is at least 1 valid digit, and
; ecx contains # digits
; bl still contains first digit as ascii
; Normally we process 3 digits at a time. But the number of
; digits to process might not be an even multiple of 3.
; This code finds the 'remainder' when dividing ecx by 3.
; It might seem like you could just use 'div' (and you can),
; but 'div' is so insanely expensive, that doing all these
; lines is *still* cheaper than a single div.
mov eax, ecx
mov edx, 0AAAAAAABh
mul edx
shr edx, 1
lea edx, [edx+edx*2]
sub ecx, edx ; This gives us the remainder (0-2).
; If the remainder is zero, use the normal 3 digit load
jz LoadTriplet
; -----------------------
; Build a triplet from however many leading 'odd' digits
; there are (1 or 2). Result is in al.
lea eax, DWORD PTR [ebx-48] ; This get us the first digit
; If there was only 1 digit, don't try to load 2
cmp cl, 1
je OneDigit
; Load the other digit
shl al, 2
mov bl, BYTE PTR [esi+1]
sub bl, 48
or al, bl
OneDigit:
add esi, ecx ; Update our pQuat pointer
jmp ProcessDigits
; -----------------------
; Build a triplet from the next 3 digits.
; Result is in al.
; bl contains the first digit as ascii
LoadTriplet:
lea eax, DWORD PTR [ebx-48]
shl al, 4 ; Make room for the other 2 digits.
; Second digit
mov cl, BYTE PTR [esi+1]
sub cl, '0'
shl cl, 2
or al, cl
; Third digit
mov bl, BYTE PTR [esi+2]
sub bl, '0'
or al, bl
add esi, 3 ; Update our pQuat pointer
; -----------------------
; At this point
; al: Triplet
; ch: DigitWritten (initially zeroed when computing remainder)
ProcessDigits:
mov dl, al
shr al, 3 ; left digit
and dl, 7 ; right digit
; If we haven't written any digits, and we are
; about to write a zero, skip it. This deals
; with both "000123" and "2" (due to OneDigit,
; the 'left digit' might be zero).
; If we haven't written any digits yet (ch == 0), and the
; value we are are about to write is zero (al == 0), skip
; the write.
or ch, al
jz Skip1
add al, '0' ; Convert to ascii
mov BYTE PTR [edi], al ; Write a digit
inc edi ; Update pointer to output buffer
jmp Skip1a ; No need to check again
Skip1:
or ch, dl ; Both check and update DigitWritten
jz Skip2
Skip1a:
add dl, '0' ; Convert to ascii
mov BYTE PTR [edi], dl ; Write a digit
inc edi ; Update pointer to output buffer
Skip2:
; Load the next digit.
mov bl, BYTE PTR [esi]
test bl, bl
jnz LoadTriplet
; -----------------------
; All digits processed. We know there is at least 1 valid digit
; (checked on entry), so if we never wrote anything, the value
; must have been zero. Since we skipped it to avoid
; unnecessary preceding zeros, deal with it now.
test ch, ch
jne WriteNull
mov BYTE PTR [edi], '0'
inc edi
; -----------------------
; Write the trailing NULL. Note that if the returned string is
; 0 bytes long, an error occurred (probably invalid digits).
WriteNull:
mov BYTE PTR [edi], 0
; -----------------------
; Cleanup
pop edi
pop ebx
pop esi
Failed:
ret
#PrintOct#8 ENDP
end
I've run a string with 1,000,000,000 quaternary digit thru it as well as all the values from 0-4,294,967,295. Seems to work.
I for one welcome our new 4-digited alien overlords.

Algorithm to assembly x86?

I have been for some days trying to translate an algorithm to assembly x86, and I did it. However I would like to print the final result that it is saved in "tmp", what instruction can I use? (I'm Spanish so I'm sorry if I say something wrong in English).
This is my algorithm:
tmp = NOT(L0)
tmp = tmp AND L1
tmp = NOT(NOT(tmp) OR NOT(L2))
tmp = NOT(tmp OR NOT(L3))
tmp = NOT(tmp + NOT(L4))
if (tmp == L5)
licence = correct
else
licence = incorrect
And this is it in assembly:
LicenceCorrect PROC
push ebp
mov ebp,esp
push ebx
push ecx
push edx
mov ebx, [ebp+8]
mov edx,[ebx]
mov ecx,edx
not ecx
mov edx,[ebx+4]
and ecx,edx
mov edx,[ebx+8]
not edx
not ecx
or ecx,edx
not ecx
mov edx,[ebx+16]
not edx
or ecx,edx
not ecx
;if
mov edx,[ebx]
cmp ecx,edx
jne cons
mov al,0
jmp next
cons:
mov al,1
next:
pop edx
pop ecx
pop ebx
pop ebp
ret
LicenceCorrect ENDP
END
Next code displays a number in AX (made with EMU8086). What MissPaper must do now is insert your procedure (LicenseCorrect) at the end of next code, and call it after "call dollars", then assign the value to AX (remove "12345").
Here it is for 32 bits:
.model small
.stack 100h
.data
buffer db 6 dup(?)
.code
start:
;INITIALIZE DATA SEGMENT.
mov ax, #data
mov ds, ax
;FIRST, FILL BUFFER WITH '$' (NECESSARY TO DISPLAY).
mov si, offset buffer
call dollars
;SECOND, CONVERT NUMBER TO STRING.
mov ax, 12345
mov si, offset buffer
call number2string
;THIRD, DISPLAY STRING.
mov dx, offset buffer
call printf
;FINISH PROGRAM.
mov ax, 4c00h
int 21h
;-----------------------------------------
;PARAMETER : DX POINTING TO '$' FINISHED STRING.
printf proc
mov ah, 9
int 21h
ret
printf endp
;------------------------------------------
;FILLS VARIABLE WITH '$'.
;USED BEFORE CONVERT NUMBERS TO STRING, BECAUSE
;THE STRING WILL BE DISPLAYED.
;PARAMETER : SI = POINTING TO STRING TO FILL.
dollars proc
mov cx, 6
six_dollars:
mov bl, '$'
mov [ si ], bl
inc si
loop six_dollars
ret
dollars endp
;------------------------------------------
;CONVERT A NUMBER IN STRING.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE, STORE
;THEM IN STACK, THEN EXTRACT THEM IN REVERSE
;ORDER TO CONSTRUCT STRING (STR).
;PARAMETERS : AX = NUMBER TO CONVERT.
; SI = POINTING WHERE TO STORE STRING.
number2string proc
mov bx, 10 ;DIGITS ARE EXTRACTED DIVIDING BY 10.
mov cx, 0 ;COUNTER FOR EXTRACTED DIGITS.
cycle1:
mov dx, 0 ;NECESSARY TO DIVIDE BY BX.
div bx ;DX:AX / 10 = AX:QUOTIENT DX:REMAINDER.
push dx ;PRESERVE DIGIT EXTRACTED FOR LATER.
inc cx ;INCREASE COUNTER FOR EVERY DIGIT EXTRACTED.
cmp ax, 0 ;IF NUMBER IS
jne cycle1 ;NOT ZERO, LOOP.
;NOW RETRIEVE PUSHED DIGITS.
cycle2:
pop dx
add dl, 48 ;CONVERT DIGIT TO CHARACTER.
mov [ si ], dl
inc si
loop cycle2
ret
number2string endp
end start
Now the 64 bits version (for much bigger numbers in EAX), made with GUI Turbo Assembler x64 (http://sourceforge.net/projects/guitasm8086/):
.model small
.586
.stack 100h
.data
buffer db 11 dup(?)
.code
start:
;INITIALIZE DATA SEGMENT.
mov ax, #data
mov ds, ax
;FIRST, FILL BUFFER WITH '$' (NECESSARY TO DISPLAY).
mov esi, offset buffer
call dollars
;SECOND, CONVERT NUMBER TO STRING.
mov eax, 1234567890
mov esi, offset buffer
call number2string
;THIRD, DISPLAY STRING.
mov dx, offset buffer
call printf
;FINISH PROGRAM.
mov ax, 4c00h
int 21h
;-----------------------------------------
;PARAMETER : DX POINTING TO '$' FINISHED STRING.
printf proc
mov ah, 9
int 21h
ret
printf endp
;------------------------------------------
;FILLS VARIABLE WITH '$'.
;USED BEFORE CONVERT NUMBERS TO STRING, BECAUSE
;THE STRING WILL BE DISPLAYED.
;PARAMETER : ESI = POINTING TO STRING TO FILL.
dollars proc
mov cx, 11
six_dollars:
mov bl, '$'
mov [ esi ], bl
inc esi
loop six_dollars
ret
dollars endp
;------------------------------------------
;CONVERT A NUMBER IN STRING.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE, STORE
;THEM IN STACK, THEN EXTRACT THEM IN REVERSE
;ORDER TO CONSTRUCT STRING (STR).
;PARAMETERS : EAX = NUMBER TO CONVERT.
; ESI = POINTING WHERE TO STORE STRING.
number2string proc
mov ebx, 10 ;DIGITS ARE EXTRACTED DIVIDING BY 10.
mov cx, 0 ;COUNTER FOR EXTRACTED DIGITS.
cycle1:
mov edx, 0 ;NECESSARY TO DIVIDE BY EBX.
div ebx ;EDX:EAX / 10 = EAX:QUOTIENT EDX:REMAINDER.
push dx ;PRESERVE DIGIT EXTRACTED (DL) FOR LATER.
inc cx ;INCREASE COUNTER FOR EVERY DIGIT EXTRACTED.
cmp eax, 0 ;IF NUMBER IS
jne cycle1 ;NOT ZERO, LOOP.
;NOW RETRIEVE PUSHED DIGITS.
cycle2:
pop dx
add dl, 48 ;CONVERT DIGIT TO CHARACTER.
mov [ esi ], dl
inc esi
loop cycle2
ret
number2string endp
end start
I didn't add your procedure because it uses the stack and I don't know what values to push before calling it.

Resources