Jump to content
  • Advertisement
Sign in to follow this  
h3ro

A few basic assembly questions

This topic is 3627 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hallo, I am trying to understand some inline asm code that I have. The commends for the code is written by me, I am wondering, is it correct?
// Move the adress of the pointer into ecx
mov	ecx, DWORD PTR unsigned_short_dataPtr
// Move the first element in the pointer into al
movzx	al, BYTE PTR [ecx+2]
// Move the first 8 bits of eax (which is al) into xmm0
movd	xmm0, eax
Questions: 1. My original data are unsigned shorts (but all in the range if 0-255), would moving them into al which is a 8bit register cause the number to be converted into a unsigned char? 2. Why do I have to do [ecx+2] to get the first element of the pointer? 3. Can I load 4 values into al-dl and then use eax as it was a int that was packed with 4 chars? movzx al, BYTE PTR [ecx+2] movzx bl, BYTE PTR [ecx+6] movzx cl, BYTE PTR [ecx+10] movzx dl, BYTE PTR [ecx+14] // Moved al-dx into xmm0 movd xmm0, eax If that is correct, how is the data then aligned? I am going to use the SSE2 commands that work on data sets of 8 (16bit ints). Thanks for reading

Share this post


Link to post
Share on other sites
Advertisement
1. In x86 assembly, the data is not signed or unsigned. The instructions get to choose whether to treat their operands as signed or unsigned. For example, read the difference between IMUL and MUL.

2. Maybe your data is not aligned? Normally you would not need to add 2 to dereference a pointer.

3a. EAX does not contain BL, CL, or DL. The letters A B C and D never mix. Here's how EAX and its "subregisters" overlap. The same holds true for ECX, EDX, and EBX.



(memory layout order) (logical order)

| +0 | +1 | +2 | +3 | | +3 | +2 | +1 | +0 |
| EAX | | EAX |
| AX | | AX |
| AL | AH | | AH | AL |



3b. movzx means 'MOVe data and Zero-eXtend). This is only necessary when moving a small operand into a larger operand (8 -> 16/32 or 16 -> 32). Your example is moving bytes into byte registers, so you don't need the ZX extension.

(side note!) There is also 'movsx' (MOVe data and Sign-eXtend). This copies the sign bit of the input value into all of the 'new' bits in the larger destination. The effect is that your signed value will still be the same. Example: (0xFF is -1, if you zero extend it, you get 0x00FF which is 255, not -1. If you sign extend it, it becomes 0xFFFF, which is -1.)

3c. There are no sub-registers for the highest two bytes of EAX, so you probably want to do something in two stages:


mov al, byte ptr [ecx+10]
mov ah, byte ptr [ecx+14]
shl eax, 16
mov al, byte ptr [ecx+2]
mov ah, byte ptr [ecx+6]


OR, you could design your data so that it is pre-packed in memory and can be loaded into EAX or XMM0 all in one move:


mov eax (or movd XMM0), dword ptr [ecx+2] // assuming you have a pre-packed DWORD instead of four separate DWORDs


[Edited by - Nypyren on July 18, 2008 12:22:19 PM]

Share this post


Link to post
Share on other sites
Thank you very very much!

Thanks for showing how the registers work. I tried to find it only, but could not find anything simple.

My data is not aligned. The function I am working on now only uses every 4th member of the dataPtr. As there is a equal step between each data, is there maybe a tricks I can use to speed it up?

In the following code, is there any point of making eax 0?

xor eax, eax
mov al, BYTE PTR [ecx+2]
movd xmm0, edx


Would this be a better solution:

movd xmm0, BYTE PTR [ecx+2]

Share this post


Link to post
Share on other sites
Quote:
Original post by h3ro
In the following code, is there any point of making eax 0?

xor eax, eax
mov al, BYTE PTR [ecx+2]
movd xmm0, edx


Would this be a better solution:

movd xmm0, BYTE PTR [ecx+2]


When you set AL to some value, it ONLY overwrites that sub-section of the larger registers.

For instance, if you have 0x12345678 in EAX from some previous instructions (EAX will *always* have something in it), and you "mov AL, 0", EAX will then become 0x12345600. Notice all of the other junk that was in EAX is still there! That's why code often sets the entire thing to zero just to be safe.


You need to be careful with your registers, too:


xor eax, eax
mov al, BYTE PTR [ecx+2]
movd xmm0, edx // don't you really want to read from eax?



Quote:
Original post by h3ro
Would this be a better solution:

movd xmm0, BYTE PTR [ecx+2]


Unfortunately, x86 assembly is a bit strict with how it allows you to MOV between different sizes of data. Each instruction expects *exact* data sizes, and sometimes they can't be mixed. "MOVD" is hardcoded to move 32-bits to-or-from an xmm register (the D stands for DWORD), so it won't work with "byte ptr [ecx+2]".

This is why you have to move your byte into a 32-bit register (EAX in this case) first before loading that into the XMM register.

Share this post


Link to post
Share on other sites
Quote:
Original post by h3ro

xor eax, eax
mov al, BYTE PTR [ecx+2]


It's been a while, but I think you can replace these two lines by the following line:

movzx eax, BYTE PTR [ecx+2]

Share this post


Link to post
Share on other sites
Quote:
Original post by DevFred
Quote:
Original post by h3ro

xor eax, eax
mov al, BYTE PTR [ecx+2]


It's been a while, but I think you can replace these two lines by the following line:

movzx eax, BYTE PTR [ecx+2]


Yeah, you can do that as well. I don't think MOVD has a ZX version, so the byte will still have to be moved into EAX before you move into XMM0.

Share this post


Link to post
Share on other sites
Thank you both.

I think I should be able to write my function now. Thanks for clarifying :)

Share this post


Link to post
Share on other sites
Is it possible to go somewhere to find a list over how expensive different assembly commands are? For example I know that division is a lot slower then say multiplication.

Share this post


Link to post
Share on other sites
Quote:
Original post by h3ro
Is it possible to go somewhere to find a list over how expensive different assembly commands are? For example I know that division is a lot slower then say multiplication.


that actually varies from processor to processor (e.g. one instruction could take 4 clocks on 286, but 1 clock on 486), here's a reference for old Pentium processors: http://faydoc.tripod.com/cpu/

Share this post


Link to post
Share on other sites
Predicting how long a modern processor (i.e., anything since the Pentium II) takes to run a particular instruction has gotten really complicated, and the manufacturers don't even give enough information to figure it out. There are several reasons for this: instruction pipelines, heterogeneous instruction decoders, speculative execution, shadow registers, branch prediction, caches... In the end you are left with a lot of trial and error.

That being said, you can assume that instructions go in groups roughly like this:
1) Assignments, bitwise arithmetic, bit shifts, addition, subtraction, comparing: Usually will be very fast (1 cycle or less) and you will be limited by memory access speed, unless you are only using registers.
2) Multiply: This used to be much more expensive than the previous group, but I think recent processors have brought this down to 1-3 cycles.
3) Divide: This is still very slow
4) Conditional branches: Very cheap if the processor can predict well whether a jump will happen or not; quite expensive if the prediction fails often.

Floating-point operations used to be very expensive, but these days addition, subtraction and multiplication can be assumed to be fast. Converting between integers and floating point is still expensive, and transcendental functions (e.g., sqrt, sin, cos, exp, log...) are even more expensive.

Also, cache misses are very expensive.

For any more details, I suggest you try to do some timings of your own.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!