How can I add 2 numbers that their value is on base 16 and make the result on "base 10" on assembler. For example:
"5h+5h=10h" - I know it's wrong, I just want it to be visually 10h
And not:
5h+5h=Ah
CODE:
MOV AX,5h
MOV BX,5h
ADD AX,BX
result: ax=Ah - Not the result that i want...
result: ax=10h - The result that i want.
I tried to figure it out with google but didn't find anything that can help me...
Here is the code you are looking for
MOV AX,5h
MOV BX,5h
ADD AX,BX
DAA
Now AX contains 10h
Ok so i figure it out with #Fifoernik 's help
so the problem is that if i want to do it with 16bit (for example 99h+1h) values i need to do it like this using DAA operan and CF flag
pop ax
pop bx
add al,bl
daa ; dec id values
mov cl,al
mov al,ah
jc Carry; do i have carry
add al,bh
daa ; do the magic thing
JMP finito
Carry:
add al,1 ; add the carring...
add al,bh
daa ;can some one tell me what exactly daa does?
finito:
mov ch,al
push cx
ret
daa working only on AL so you'ill need to use the carry flag to add the carry like:
AH AL
1 <----- carry
00 99 <-- DAA take care of the 99 and make it 0 when its A0h
00 01+
-- --
01 00 ---> result 100h
Related
I'm currently struggling in outputting AzByCx in ms debug since I don't really know too much about it.
Included here are the Basic commands that my teacher sent to us.
I can output A-Z easily, but not AzBxCy, there's not much of a detailed tutorial online so I came here to ask.
-e 200 "Az"
-a
1BD8:0100 mov bx, word [200]
1BD8:0104 mov cx, 3
1BD8:0107 mov ah, 2
1BD8:0109 mov dl, bl
1BD8:010B int 21
1BD8:010D mov dl, bh
1BD8:010F int 21
1BD8:0111 add bx, FF01
1BD8:0115 loop 109
1BD8:0117 mov dl, 0D
1BD8:0119 int 21
1BD8:011B mov dl, 0A
1BD8:011D int 21
1BD8:011F mov ax, 4C00
1BD8:0122 int 21
1BD8:0124
-g
AzByCx
What does this do?
initialises word at ds:200h to the string "Az" (little endian low byte is "A", high byte is "z")
use A command to assemble the following program:
load from memory into register bx (to initialise the register without having to look up the numeric ASCII codepoints)
set up cx as loop counter for three iterations
set up register ah for the interrupt 21h service 02h (display character in dl)
display character read from bl (low byte of bx)
display character from bh (high byte of bx)
add 1 to bl and -1 (in two's complement resulting in 0FFh) to bh which increments the codepoint in bl and decrements the one in bh
loop back to display subsequent letters
display a linebreak (codepoints 13 and 10, or 0Dh 0Ah) to make the output easier to read
terminate program
use G command to run the program
Microsoft DEBUG.EXE can indeed be used to write a simple program in Intel-syntax assembly, see this example. Replace the string definition db "Hello world$" with db "AzByCx$" and you're done.
However, this is definitely not a good way how to learn assembly language.
Find a better teacher.
I want to put numbers from 0 - 9 to memory cells 400h to 409h.
So for example at 400h -> 0 (put 0) and at 401h -> 1 (put 1) ..... 409h (put 9).
This is my code so far: (I dont know if it works)
IDEAL
MODEL small
STACK 100h
DATASEG
;----------
;----------
CODESEG
start:
mov ax , #data
mov ds , ax
mov es, ax
;----------
mov si , 400h
mov cx , 10
mov al , 0
agian:
mov [si],al
inc si
inc al
loop agian
;--------
exit:
mov ax,4c00h
int 21h
END start
There's a very simple way to see if your program works. Just write the values in the video memory. That way you'll know if it works.
start:
mov ax, 0B800h ;NEW
mov ds, ax
mov es, ax
;----------
mov si, 400h
mov cx, 10
mov al, 48 ;NEW value 0 -> character 0
agian:
mov [si], al
add si, 2 ;NEW 1 character occupies 2 bytes in video memory
inc al
loop agian
mov ah,00h ;NEW wait for a keystroke so you can actually see
int 16h ;NEW ... the output
If you can invest the time you could learn to use the DOS utility DEBUG.EXE. Amongst other things it allows you to single step your program and view memory .
The easiest way to check if your ASM code is working the way you expect is to run it in a debugger. If you're running on Windows, OllyDbg 2 would be a good candidate — it will show you the current values of the registers, state of the stack, etc., so you can see how they change as you step through your code. You can modify the code from inside OllyDbg too.
You can write breakpoints in your code with the int 3 instruction, or use the debugger to place breakpoints at runtime.
So I am working on a Binary Bomb assignment and have gotten stuck. Tried looking at other questions and guides but mine seems to be completely different from what is described in other questions and guides I found on the web.
The phase only takes 2 unsigned ints for input. Here it is disassembled in gdb after being run with 11 2 as input.
Dump of assembler code for function phase_5:
0x08048ccc <+0>: push %ebp
0x08048ccd <+1>: mov %esp,%ebp
0x08048ccf <+3>: push %esi
0x08048cd0 <+4>: push %ebx
=> 0x08048cd1 <+5>: sub $0x20,%esp
0x08048cd4 <+8>: lea -0x10(%ebp),%eax
0x08048cd7 <+11>: mov %eax,0xc(%esp)
0x08048cdb <+15>: lea -0xc(%ebp),%eax
0x08048cde <+18>: mov %eax,0x8(%esp)
0x08048ce2 <+22>: movl $0x8049b0a,0x4(%esp)
0x08048cea <+30>: mov 0x8(%ebp),%eax
0x08048ced <+33>: mov %eax,(%esp)
0x08048cf0 <+36>: call 0x8048788 <__isoc99_sscanf#plt>
0x08048cf5 <+41>: cmp $0x1,%eax
0x08048cf8 <+44>: jg 0x8048cff <phase_5+51>
0x08048cfa <+46>: call 0x80492b6 <explode_bomb>
0x08048cff <+51>: mov -0xc(%ebp),%eax
0x08048d02 <+54>: and $0xf,%eax
0x08048d05 <+57>: mov %eax,-0xc(%ebp)
0x08048d08 <+60>: cmp $0xf,%eax
0x08048d0b <+63>: je 0x8048d36 <phase_5+106>
0x08048d0d <+65>: mov $0x0,%ecx
0x08048d12 <+70>: mov $0x0,%edx
0x08048d17 <+75>: mov $0x8049960,%ebx
0x08048d1c <+80>: add $0x1,%edx
0x08048d1f <+83>: mov (%ebx,%eax,4),%eax
0x08048d22 <+86>: add %eax,%ecx
0x08048d24 <+88>: cmp $0xf,%eax
0x08048d27 <+91>: jne 0x8048d1c <phase_5+80>
0x08048d29 <+93>: mov %eax,-0xc(%ebp)
0x08048d2c <+96>: cmp $0xb,%edx
0x08048d2f <+99>: jne 0x8048d36 <phase_5+106>
0x08048d31 <+101>: cmp -0x10(%ebp),%ecx
0x08048d34 <+104>: je 0x8048d3b <phase_5+111>
0x08048d36 <+106>: call 0x80492b6 <explode_bomb>
0x08048d3b <+111>: add $0x20,%esp
0x08048d3e <+114>: pop %ebx
0x08048d3f <+115>: pop %esi
0x08048d40 <+116>: pop %ebp
0x08048d41 <+117>: ret
For the line 0x08048d17 <+75>: mov $0x8049960,%ebx
I used
x/16b 0x8049960
gdb and it tells me
0x8049960 array.2954: 10 0 0 0 2 0 0 0
0x8049968 array.2954+8: 14 0 0 0 7 0 00
When I go through the program using until until I get to
0x08048d31 <+101>: cmp -0x10(%ebp),%ecx
%edx = 11, %ecx = 82, and %ebp-0x10 = 2 (used print to get values for first two and x/d $ebp-0x10 for last one)
Because 82 != 2 it just goes to call explode_bomb.
From what I understand it is reading in my 2 numbers, making sure I entered 2 at <+41>.
Then it grabs the first number from the array which in this case is 10 and puts it into $eax at +=<+51>. Then it puts eax into -0xc($ebp) at <+57>.
Then it checks to make sure $eax isn't 15 at <+60>, goes on to set $ecx, and $edx to 0. It then passes the pointer to the array to $ebx at <+75>.
Then it enters a loop from <+80> to <+91> but I am not sure what it is really doing. I get that it increments $edx by 1 and the loop is exited when $eax is 15, but I cant figure out how the rest of the stuff works out.
Am I understanding it correctly up to the loop part? And, if someone wouldn't mind explaining what is happening between <+80> and <+91> I would be very grateful.
p.s. Sorry if my formatting is wrong.
Then it grabs the first number from the array which in this case is
10 and puts it into $eax at +=<+51>.
Wrong. <+51> reads the first number you entered, not the first number from the array. It's then masked into the 0..15 range by discarding the top bits, and is written back to the local variable where it came from. It also lives on in eax, of course.
The array contains 4 byte integers and there are 15 of them. As such you can print it using x/15wd.
Now to the loop. edx is obviously just keeping track of the iteration count, no surprise there. <+83> is the interesting part: it replaces eax with the value of the array item whose index eax currently holds. That is eax = array[eax]. ecx is of course just summing up the array elements you have visited, that's again easy. The exit condition is when you hit the array item that has value 15.
What it all boils down is that this array is really a linked list. The end of the list is marked by a 15. The first number you enter is used as a starting point for list traversal. It should be selected such that you have 11 elements until the end of the list (see <+96>). The second input number should equal the sum of the array items visited.
I've tried reading about this all over the internet but here it is my problem. I am given a string of doublewords.
I have to order in decreasing order the string of the low words (least significant) from these doublewords. The high words remain unchanged.
For ex: strin DD 12345678h 1256ABCDh, 12AB4344h
the result would be 1234ABCDh, 12565678h, 12AB4344h.
Now I tried my best writting some code but it's not working properly, my insertion procedure. If you could take a look and tell me what I'm doing wrong, I'd be greatful.
I tried running it in td mode but I just can't figure out.
assume cs:code, ds:data
data segment
s dd 12345678h, 1256ABCDh, 12AB4344h
ls equ ($-s)/4 ;this is supposed to be the length of my source string
d dd ls dup (?) ;this is my destination string
aux dw ?
aux2 dw ?
data ends
code segment
insert proc
push di ;here I use the stack to get more free registers
push cx
cmp di, offset d ;if di=offset d it means that I didn't store any number yet
je addPrim
std ;we plan on working form right to left on the string for the next part
mov cx, di
sub cx, offset d ;here I find out with how many words I have to compare the word from AX
dec di
dec di ;since I work with doublewords, for some reason I thought I should decrease di
dec di ;3 times but here my procedure gets fuzzy and doesn't work properly anymore
repeta1: ;this repeat is supposed to compare the word from AX with the rest of the least
scasw ;significant words from es:di
jge DIplus2 ;if my number from AX is bigger or equal than what's in es:di, I increment
;di twice and store it
mov bx, word ptr es:[di+1] ;this part is supposed to interchange words but it's not
;working how I planned so I don't know how to change it
mov word ptr es:[di+2], bx
loop repeta1
jmp DIplus1
DIplus2:
inc di
DIplus1:
inc di
addPrim: ;this label just adds the first word in the destination string
stosw
pop cx
pop di
inc di
inc di
cld
ret
insert endp
start:
mov ax, data
mov ds, ax
mov es, ax
mov si, offset s
mov di, offset d
mov cx, ls ; store in cx the length of the strings
jcxz exit
repeta:
lodsw ;because of little endian, my first word will be my least significant word in the
;in the doubleword so right after it is moved in ax, i apply the procedure insert
call insert
lodsw ;here it moves in ax my most significan word in the dd, so i auto store it
stosw ;in my destination string
loop repeta
exit:
mov ax, 4c00h
int 21h
code ends
end start
ls equ ($-s)/4 ;this is supposed to be the length of my source string
This actually calculates the number of elements.
mov cx, di
sub cx, offset d ;here I find out with how many words ...
At the second invocation of your insert proc this will set CX=4 which is too big given a list of only 3 values. I suggest you divide CX by 4.
dec di
dec di ;since I work with doublewords...
dec di ;3 times but here my procedure gets fuzzy
This is certainly wrong. SCASW indicates you either decrement by 4 or not decrement at all!
mov bx, word ptr es:[di+1] ;this part is supposed to interchange words...
mov word ptr es:[di+2], bx
This cannot work since the offsets are only 1 byte apart!
jmp DIplus1
This yields an single increment of DI and thus an error because you want to store a word at that spot.
First of all, thanks for all the help thus far.
Complete code can be found here
I have trouble understanding these lines. I wrote some comments...
The line, for example, mov es:[si+6], al means move data in al to the memory address marked by si+6 (I think this would be an offset calculation).
Then what is add si,40 in the loop?
Any helps mean everything to me! Thank you.
L0_95: ; this segment prints ASCII code 0 - 95
mov si,6 ; refers to the string we declared at the beginning
mov cx,4 ; I think this is the height?
C1A:
; this loop adds the name of the column
mov al,string[0]
mov es:[si],al
mov al,string[2]
mov es:[si+6],al
mov al,string[4]
mov es:[si+24],al
mov al,string[6]
mov es:[si+28],al
add si,40 ;;;; what is this line?
loop C1A
mov si,122 ;;;; and these three lines?
mov bx,0
mov cx,4
C1B:push cx
mov cx,24
add si,40
C1C:push cx
call DEC_CONVERT
add si,2
call HEX_CONVERT
add si,2
call BIN_CONVERT
add si,2
call CHAR_CONVERT
inc bx
add si,126
pop cx
loop C1C
pop cx
sub si,3840
loop C1B
ret
L96_191:
add si advances the si register by 40.
mov si,122 sets the si register to 122, probably the address of some data. The remaining two instructions should now be self-explanatory.