News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Few Questions..

Started by Xycron, December 27, 2012, 11:21:19 AM

Previous topic - Next topic

Xycron

I've been programming in C# for a couple years now and I'm trying to learn the basics of assembly with masm before I take a course in it next semester. I'm supposed to know the basics before starting, and there is a worksheet I should be able to figure out. I'm having some trouble getting into it without any instruction.

The first half of it is converting numbers to/from different bases, which I remembered well enough from my intro to CS classes a few years ago.

1) Here is one question, that I believe I have correct but was hoping you guy could confirm it for me.

Complete the following table. All numbers are to be represented in the base 16
Quote
ASSEMBLY LANGUAGE  CODE                     EAX
mov eax, 1                                             1
sub eax, 9ADF01                                         FF652100
I had to fill in the EAX column. I used visual studio, put the lines in, did a break point, and used the intermediate window to find out what was in eax. Is this correct?


2) Next question:

QuoteAssume in an AL program:

    x     DWORD      110101111010101000110101101101b

0011   0101   1110   1010   1000   1101   0110   1101

The additive inverse of x is

My understanding is that for binary numbers, to get the negative number, you inverse the 1/0s and then add an extra 1 to the right of the number. However, on this worksheet where the anwser goes its split up into boxes that imply 4 numbers should go per box, which doesn't leave room for the extra 1. This has left me a little confused... Anyone have any idea here? I'll probably end up with more questions as I go down the sheet, but I'm going to give them a go first and see if I can figure those out on my own. These first two I seem to be stuck on.

jj2007

Quote from: Xycron on December 27, 2012, 11:21:19 AM
The additive inverse of x is

Wiki: In mathematics, the additive inverse, or opposite, of a number a is the number that, when added to a, yields zero.

include \masm32\MasmBasic\MasmBasic.inc        ; download
        Init

        mov eax, 1
        sub eax, 9ADF01h
        Print Hex$(eax)        ; FF652100 indeed

        mov ecx, 110101111010101000110101101101b
        mov ebx, ecx        ; keep a copy in a safe register
        Print Bin$(ecx), CrLf$
        neg ecx        ; there it is!
        add ebx, ecx        ; the test for additive inverse
        Print Bin$(ecx), CrLf$
        Inkey Str$("ebx=%i", ebx)
        Exit
end start

Output:
00110101111010101000110101101101
11001010000101010111001010010011
ebx=0

q.e.d.

Tedd

1) Is correct -- try doing it by hand first, then check your answers with the debugger.

2) You invert the bits and then add 1 (the value, not append an extra 1.)

example:
  5 = 00000101
  invert: 11111010
  plus 1: 11111011
  11111011 = -5
Potato2

jj2007

Quote from: Tedd on December 28, 2012, 03:03:02 AM
2) You invert the bits and then add 1

Any difference from neg eax?

dedndave

flags   :P

also - NEG on a 32-bit machine is good for bytes, words, dwords

if you want to negate other sizes or use SSE to do them in parallel,
then the invert/add1 or sub1/invert method is nice to know

Tedd

Quote from: jj2007 on December 28, 2012, 05:16:02 AM
Quote from: Tedd on December 28, 2012, 03:03:02 AM
2) You invert the bits and then add 1

Any difference from neg eax?

Neg performs the same function, but knowing that doesn't help with understanding the theory and why it works.
Potato2

Xycron

Thank you both for the help!

I have another one... about div. My question comes from a chart below. On the last line you can see pseduo code is diving eax / m. but the assemlby language code is just div m. How does it know to divide divide m by eax? is it just because eax was the last variable? I'm not sure I understand what is happening there.

QuotePSEUDO-CODE   AL -CODE    EAX
                                                                  
N :=ff ff ff fah            n dword 0ff ff ff fah    
M:= 10h                    m dword 10h         
EAX:= N                    mov eax, n   
EDX:= 0                    mov edx, 0   
EAXĂ·M                   div m   

Thanks again for the help everyone.


dedndave

for the DIV instruction (as well as MUL), the size of the operand determines the behaviour of the instruction
the assembler knows what the size of the divisor is and selects the opcode accordingly
for a dword size divisor, EDX:EAX is treated as one large 64-bit dividend

http://www.masmforum.com/board/index.php?topic=18841.msg159697#msg159697

for byte or word sizes, it uses different register sets
but, the dividend is always twice as many bits as the divisor

MichaelW

The description in the MASM reference is:
Quote
DIV
Unsigned Divide

Divides an implied destination operand by a specified source operand.

For a 32-bit source operand the implied destination operand is EDX:EAX.
Well Microsoft, here's another nice mess you've gotten us into.

Xycron

At first I thought I understood it as:
So, 'div x' will do x / eax and the result will be in edx?

but now it sounds like the result is stored in edx and eax? and it will always divide by what was in eax first? I'm still a bit confused.

Could you explain what the : syntax means in EDX:EAX?

Sorry, I really am brand new to assembly.

jj2007

Don't worry, we are good at teaching Chinese ;-)

edx::eax is a notation used for "take two 32-bit registers together and see them as a 64-bit number"
div memvar divides the 64-bit number in edx::eax by memvar. The quotient will be stored in eax, the remainder in edx

With mov edx, 0 you declare implicitly that you want an unsigned division of eax; because now the highest bit of the edx::eax is zero.

To get signed division, you can use cdq to sign-extend the value of eax into edx, i.e.
.if sdword ptr eax<0
  ... edx=-1
.else
  ... edx=0
.endif

Of course, you can also explicitly load a 64-bit number into edx::eax and divide it by something. The result is always 32-bit only.

Here is an example:

include \masm32\MasmBasic\MasmBasic.inc        ; download
.data
MyQW        QWORD 1234567890123456789
My1e18      QWORD 1000000000000000000        ; 1e18

        Init

        PrintLine Str$("A fat number:\t%i", MyQW)

        mov eax, dword ptr MyQW        ; dword ptr means override qword size
        mov edx, dword ptr MyQW[4]        ; load the high dword of MyQ
        pushad        ; save all regs - eax and edx will be trashed by the printing
        PrintLine Str$("As edx::eax:\t%i", edx::eax)
        popad        ; still MyQW
        mov ecx, 123
        if 0                ; conditional assembly: if 0 means "don't do that"
                div ecx        ; this will cause an exception, because the result of the division does not fit into 32 bits
                PrintLine Str$("Divided by 123:\t%i", eax)
        else
                cdq        ; sign-extend eax into edx; since eax is positive, edx will be zero
                div ecx        ; divide the lower dword of MyQW by ecx
                PrintLine Str$("eax div 123:\t%i", eax)
        endif
        mov eax, dword ptr My1e18
        mov edx, dword ptr My1e18[4]
        mov ecx, 1000000000        ; 1e9
        div ecx
        PrintLine Str$("My1e18 div 1e9:\t%i", eax)

        Inkey
        Exit
end start

Output:
A fat number:   1234567890123456789
As edx::eax:    1234567890123456789
eax div 123:    17174430
My1e18 div 1e9: 1000000000

MichaelW

I think the convention (at least in the US, but what do we know) is to use a single colon to represent a 64-bit value in two 32-bit registers (EDX:EAX). The double colon notation (EDX::EAX) is for invoke.
Well Microsoft, here's another nice mess you've gotten us into.

jj2007

Quote from: MichaelW on December 29, 2012, 07:20:50 PM
I think the convention (at least in the US, but what do we know) is to use a single colon to represent a 64-bit value in two 32-bit registers (EDX:EAX). The double colon notation (EDX::EAX) is for invoke.

Michael,

Thanks for correcting me on that. You are right, of course, but I'll keep the edx::eax syntax for MasmBasic Str$() as shown above because it's closer to an "invoke situation". Is there any case where you can use edx:eax in assembly, I mean in real code that gets assembled, not in comments?

Xycron

Thanks. I think I have a better understanding now. I'll probably be posting soon on 'jumps'.. but I'm going to see if I can figure this one out first as well.

MichaelW

Quote from: jj2007 on December 29, 2012, 07:35:31 PM
Is there any case where you can use edx:eax in assembly, I mean in real code that gets assembled, not in comments?

None that I know of.
Well Microsoft, here's another nice mess you've gotten us into.