reading from File in assembly - windows

i am trying to read a username and a password from a file in x86 assembly for the perpose of authentication
obviously the file consists of two lines , the user name and the password how can i read the two lines seperately and compare them?
My attempt:
proc read_file
mov ah,3dh
lea dx,file_name
int 21h
mov bx, ax
xor si,si
repeat:
mov ah, 3fh
lea dx, buffer
mov cx, 100
int 21h
mov si, ax
mov buffer[si], '$'
mov ah, 09h
int 21h ;print on screen
cmp si, 100
je repeat
jmp stop;jump to end
stop:
RET
read_file ENDP

Go here and read up on functions like CreateFile and ReadFile.

You should use system class to do that and it depends on whether you use Windows or Linux.
Check this : http://www.freebsd.org/doc/en/books/developers-handbook/x86-system-calls.html

Related

Getting error after copying 8086 code from book

I am having troubles running this 8086 programs that take one letter input from keyboard and outputs "the letter you typed is _"
I just started reading my college book on this and trying to run some code from the book on my computer but got stuck here.
The code below is from my college book.
I am running it in emu8086 emulator.
CODE SEGMENT
; set the DS register
MOV AX, DATA
MOV DS, AX
; Read Keyboard
MOV AH, 08H
INT 21H
; Save input
MOV BL, AL
; Display first part of Message
MOV AH, 09H
MOV DX, OFFSET MESSAGE
INT 21H
; Display character of BL register
MOV AH, 02H
MOV DL, BL
INT 21H
; Exit to DOS
MOV AX, 4C00H
INT 21H
CODE ENDS
DATA SEGMENT
MESSAGE DB “The letter you typed is $”
DATA ENDS
END
The error I am getting is
INT 21h, AH=09h -
address: 00020
byte 24h not found after 2000 bytes.
; correct example of INT 21h/9h:
mov dx, offset msg
mov ah, 9
int 21h
ret
msg db "Hello$"
After further debugging by myself I have concluded there is some problem with this
MOV AX, DATA
MOV DS, AX
If I remove it from my code it executes but with some garbage in the start.
Any suggestions will be appreciated.
Update:
Image of emulator around the string "the letter you typed $"
umm so after giving up for 2 days I referenced another book, and in there they weren't using segments. So I removed segments and the program ran flawlessly here is the new code:
ORG 100H
MOV AH, 08H ; Read Keyboard
INT 21H
MOV BL, AL ; Save input
MOV AH, 09H ; Display first part of Message
MOV DX, OFFSET MESSAGE
INT 21H
MOV AH, 02H ; Display character of BL register
MOV DL, BL
INT 21H
MOV AX, 4C00H ; Exit to DOS
INT 21H
RET
MESSAGE DB "The letter you typed is $"
Thank you to everyone who tried to help me, really appreciated.

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.

TASM giving no output after compile

I have a program that compiles correctly with zero error or warning but does not display the output I cannot guess the reason for no output
.model small
.data
a dw 1234H
b dw 0100H
.code
Process:
MOV AX, #data
MOV DS, AX
Mov AX, a
MOV BX, b
SUB AX, BX
MOV CH, 04H
MOV CL, 04H
MOV BX, AX
X: ROL BX, CL
MOV DL, BL
AND DL, 0FH
CMP DL, 09
JBE Y
ADD DL, 07
Y: ADD DL, 30H
INT 21H
DEC CH
JNZ X
MOV AH, 4CH
INT 21H
END Process;
If you intend to write characters one at a time to STDOUT then DL should contain the character and AH must be set to 02H before you invoke INT 21H. So,
Y: ADD DL, 30H
MOV AH, 02H
INT 21H
You can also set AH to 02H before the loop starts, saving on the number MOV instructions.

Resources