NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: Azrael998 on October 27, 2020, 02:39:36 PM
-
Hello, everyone, I'm very new to assembly and I'm trying to convert this MASM code to NASM for an assignment, can anyone please help me?. The code is supposed to ask a user for two binary numbers add them then print their sum in binary form.
MASM code is below:
.MODEL SMALL
.STACK 100H
.DATA
PROMPT_1 DB 0DH,0AH,\'Enter the first binary number ( max 8-digits ) : $\'
PROMPT_2 DB 0DH,0AH,\'Enter the second binary number ( max 8-digits ) : $\'
PROMPT_3 DB 0DH,0AH,\'The SUM of given binary numbers in binary form is : $\'
ILLEGAL DB 0DH,0AH,\'Illegal character. Try again.$\'
.CODE
MAIN PROC
MOV AX, @DATA ; initialize DS
MOV DS, AX
JMP @START_2 ; jump to label @START_2
@START_1: ; jump label
LEA DX, ILLEGAL ; load and display the string ILLEGAL
MOV AH, 9
INT 21H
@START_2: ; jump label
XOR BX, BX ; clear BX
LEA DX, PROMPT_1 ; load and display the string PROMPT_1
MOV AH, 9
INT 21H
MOV CX, 8 ; initialize loop counter
MOV AH, 1 ; set input function
@LOOP_1: ; loop label
INT 21H ; read a character
CMP AL, 0DH ; compare AL with CR
JNE @SKIP_1 ; jump to label @SKIP_1 if AL!=0DH
CMP CX, 8 ; compare CX with 8
JE @START_1 ; jump to label @START_1 if CX=8
JMP @EXIT_LOOP_1 ; jump to label @EXIT_LOOP_1
@SKIP_1: ; jump label
AND AL, 0FH ; convert ascii into decimal code
SHL BL, 1 ; shift BL towards left by 1 position
OR BL, AL ; set the LSB of BL with LASB of AL
LOOP @LOOP_1 ; jump to label @LOOP_1 if CX!=0
@EXIT_LOOP_1: ; jump label
LEA DX, PROMPT_2 ; load and display the string PROMPT_2
MOV AH, 9
INT 21H
MOV CX, 8 ; initialize loop counter
MOV AH, 1 ; set input function
@LOOP_2: ; loop label
INT 21H ; read a character
CMP AL, 0DH ; compare AL with CR
JNE @SKIP_2 ; jump to label @SKIP_2 if AL!=0DH
CMP CX, 8 ; compare CX with 8
JE @START_2 ; jump to label @START_2 if CX=8
JMP @EXIT_LOOP_2 ; jump to label @EXIT_LOOP_2
@SKIP_2: ; jump label
AND AL, 0FH ; convert ascii into decimal code
SHL BH, 1 ; shift BH towards left by 1 position
OR BH, AL ; set the LSB of BH with LASB of AL
LOOP @LOOP_2 ; jump to label @LOOP_2 if CX!=0
@EXIT_LOOP_2: ; jump label
LEA DX, PROMPT_3 ; load and display the string PROMPT_3
MOV AH, 9
INT 21H
ADD BL, BH ; add BL and BH
JNC @SKIP ; jump to label @SKIP if CF=1
MOV AH, 2 ; print the digit 1 i.e. carry
MOV DL, 31H
INT 21H
@SKIP: ; jump label
MOV CX, 8 ; initialize loop counter
MOV AH, 2 ; set output function
@LOOP_3: ; loop label
SHL BL, 1 ; shift BL towards left by 1 position
JC @ONE ; jump to label @ONE if CF=1
MOV DL, 30H ; set DL=0
JMP @DISPLAY ; jump to label @DISPLAY
@ONE: ; jump label
MOV DL, 31H ; set DL=1
@DISPLAY: ; jump label
INT 21H ; print the character
LOOP @LOOP_3 ; jump to label @LOOP_3 if CX!=0
MOV AH, 4CH ; return control to DOS
INT 21H
MAIN ENDP
END MAIN
-
Have you assembled this with MASM and tested it? It looks to me like it will never display the error message. I could translate it to nasm code, but you need to get it working first, or at least try fixing it and ask about specific parts that don't work. I can't do all your homework without knowing you have tried :)
If I were to write code to do what you want, I would create macros and/or callable routines.
-
I don't know if this is right but this is what I currently have from reading the Assembly tutorial from tutorialspoint.com. I get the error Segmentation fault (core dumped) when I run the code in my terminal. Can you tell me what the '@' sign does in MASM. I'm only slightly familiar with NASM and I've never used MASM before.
NASM code:
section .data
msg1 db 'Enter the first binary number: ', 0DH, 0AH
msg2 db 'Enter the second binary number: ', 0DH, 0AH
msg3 db 'The sum of the given binary numbers: ', 0DH, 0AH
illegal db 'Illegal character. Try again.', 0DH,0AH
section .text
global _start
_start:
_start_1:
lea dx, illegal
mov ah, 9
int 21h
_start_2:
xor bx, bx
lea dx, msg1
mov ah, 9
int 21h
mov cx, 8
mov ah, 1
_loop_1:
int 21H
cmp al, 0DH
jne _skip_1
cmp cx, 8
je _start_1
jmp _exit_loop_1
_skip_1:
and al, 0FH
shl bl, 1
loop _loop_1
_exit_loop_1:
lea dx, msg1
mov ah, 9
int 21H
mov cx, 8
mov ah, 1
_loop_2:
int 21H
cmp al, 0DH
jne _skip_2
cmp cx, 8
je _start_2
jmp _exit_loop_2
_skip_2:
and al, 0FH
shl bh, 1
or bh, al
loop _loop_2
_exit_loop_2:
lea dx, msg3
mov ah, 9
int 21H
add bl, bh
jnc _skip
mov ah, 1
mov dl, 31H
int 21H
_skip:
mov cx, 8
mov ah, 2
_loop_3:
shl bl, 1
jc _one
mov dl, 30H
jmp _display
_one:
mov dl, 31H
_display:
int 21H
loop _loop_3
mov ah, 4ch
int 21H
ret
-
The @ tells masm that it is a label. Your code looks like it is written to be a DOS .com file. I don't know what OS your terminal is running - is it DOS? If not, that might be your problem. You don't need the _ in front of labels unless you are creating object files to link with in C (although it doesn't hurt to have them, they just aren't needed).
Also, the rewritten code will now write the error message then carry on to execute the rest of your code.
When coding, I always start by writing pseudo code (basically mapping out what routines need to happen in what order, and what I need to happen. I find that the easiest and fastest way to get everything working.
I'll take a better look after I have slept, and offer you some better suggestions, then when you have done what you can with them, I'll try to help improve your code. Is this for fun or for school?
-
Thank you very for responding this is for school. My terminal is running on manjaro linux x86_64, the MASM code was written by my professor but I don't know what OS his terminal is running on.
-
Hi Azrael998,
Welcome to the forum.
Hi Debs,
This error message sounds like Linux to me. Your Masm code won't run in Linux. In fact, it won't tun on anything but a very old machine or in an emulator = Dosbox or such. This mat ve what you're supposed to be doing. Find out!
We can rewrite this code so it will run in Linux... or you can install Dosbox or some other emulator. Which are you supposed to be doing?
Good job with the code so far. One problem: "lea" wants "[contents}" of memory. So:
lea dx, [illegal]
etc.
The other instructions are mostly the same as Masm.
Hang in there!
Best,
Frank
-
Hi Frank Kotler, thank you very much for responding. My assignment is to convert the code so that it runs on linux, how can I do that?.
-
I don't know the Linux system calls, so won't be able to help with that, but I will reply with some pseudo code later to show how I would code it. I'll leave it to our Linux users to help converting system calls to Linux syscalls.
Does the 8 you are loading into CX mean you are only working with integer strings of 7 digits plus return, or 8 digits without? Do you need to test for overflows (numbers which are too long)? I can see you want to detect invalid key presses.
-
The 8 being loaded in the CX register means 8 digits without return, yes I need to test for overflow.
-
Here is some basic pseudo code. I can expand on some of it using code that works on DOS or uses BIOS interrupts, but that would still need changing to use Linus system calls.
section .data
msg1 db 'Enter the first binary number: ', 0DH, 0AH
msg2 db 'Enter the second binary number: ', 0DH, 0AH
msg3 db 'The sum of the given binary numbers: ', 0DH, 0AH
illegal db 'Illegal character. Try again.', 0DH,0AH
str1 times 10 db 0
str2 times 10 db 0
result times 11 db 0
section .text
org 256 ; only needed if you code for a DOS environment and create a .com file
read input strings from stdin (normally keyboard)(I would create a callable routine
which takes the output address as its input)
convert ascii string to binary digits, checking each character as you go.
Store in bh and bl if the systems calls preserve them
if any input character is invalid, output error msg
if no errirs, add the resulting numbers
convert back to am ascii string
display the output
I made the strings longer than you need so that you can test for input that is too long, as well as having room for the carriage returm (to help check the length of the input). DOS has an interrupt that takes the length of input as an argument, so I assume Linux has that as well,
-
I'm planning on rewriting the code do you think it's efficient to convert the binary numbers to decimal then add them then convert the result to binary?
-
As the numbers are being input in ascii text (you are inputting the numbers as ascii codes, not as numbers) I do think it is more efficient, yes. For example, when you type "0", you are not storing 0, you are storing the ascii code, which is 30h (48 decimal). Also, by doing the conversion, you can just add the numbers in both registers (which will set the overflow flag if the result is higher than 0FFh). If you don't convert, you will still have to subtract 30h from each element, then you will have to check each element of the result to see if it is higher than "1". That just seems inefficient to me.
You will also find that, if you write efficient callable routines, they will be reusable in other apps, and will form a template you only need minor adjustments to for similar routines.
-
I have written a similar version to your last post, with some small changes. Personally I would create callable functions for repeated code, but I wanted to keep it as similar to your code as possible, to help you understand the changes.
I kept your labels so you can study each block separately. I always fully comment my code, to make it easier to understand.
This code can be assembled into a DOS .com file. I didn't test it, but believe it is OK. To convert to Linux code, you will need to look up Linux system calls and/or get more help elsewhere.
section .data
msg1 db 'Please enter the first 8-bit binary number: ', 0DH, 0AH
msg2 db 'Please enter the second 8-bit binary number: ', 0DH, 0AH
msg3 db 0DH, 0AH, 'The sum of the given binary numbers is:', 0DH, 0AH
invalid db 'Invalid input, try again.', 0DH,0AH
section .text
org 100h ; only needed if assembling as a DOS .com file
_start:
push cs
pop ds ; set data segment
xor bx, bx ; used to store input
lea dx, msg1 ;
mov ah, 9 ;
int 21h ; output first message using DOS interrupt
mov cx,8 ; loop counter
mov ah,1 ; DOS int 21h function for keyboard input
_loop_1:
int 21h ; get character input
sub al,"0" ; convert character input to binary digit
cmp al,1 ; is input a valid binary digit?
ja error ; if not, jump to error
shl bl,bl ;
add bl,al ; store this character
loop _loop_1 ; fetch next digit
int 21h ; fetch final character
cmp al,0Dh ; is this a carriage return?
ja error ; if not, jump to error
lea dx, msg2 ;
mov ah, 9 ;
int 21h ; output second message using DOS interrupt
mov cx,8 ; loop counter
mov ah,1 ; DOS int 21h function for keyboard input
_loop_2:
int 21h ; get character input
sub al,"0" ; convert character input to binary digit
cmp al,1 ; is input a valid binary digit?
ja error ; if not, jump to error
shl bh,bh ;
add bh,al ; store this character
loop _loop_2 ; fetch next digit
int 21h ; fetch final character
cmp al,0Dh ; is this a carriage return?
ja error ; if not, jump to error
lea dx, msg3 ;
mov ah, 9 ;
int 21h ; output third message using DOS interrupt
mov ah,2 ; DOS function 2 outputs a single character
adc bl,bh ; add both numbers, using carry flag for overflow
jnc _next ; if result is only 8-bits, skip this short section
mov dl,"1"
int 21h ; output "1"
_next:
mov cx,8
xor bh,bh
_loop_3:
shl bx,1
and bh,1 ; is next digit 0 or 1?
jnz _one
mov dl,"0" ; next digit is 0
jmp _display:
_one:
mov dl,"1" ; next digit is 1
_display
int 21h ; output this character
loop _loop_3
_exit:
mov ax,04C00h
int 21h ; exit with error code 0
_error:
lea dx, invalid ;
mov ah, 9 ;
int 21h ; output error message using DOS interrupt
jmp _start: