noseonarug17
noseonarug17

Reputation: 53

Converting between bytes, words, and doublewords

So I'm doing my first assignment for an x86 assembly class and I'm already lost (great). Maybe I'm reading it wrong, but it appears that I need to convert a byte to a word, which I can do, and a doubleword to a word, which I haven't the slightest idea how to do. Considering that I've done a ton of looking around, I'm guessing I'm misunderstanding what I need to do. Here's the prompt:

Assume the following definitions in the .data segment:

arrayB: db  170, 193, 57

arrayW: dw  0, 0, 0

arrayD: dd 517, 1045, 2000

Write an assembly program that is equivalent to the following high-level language statements:

arrayW[0] = arrayB[0] + arrayD[0];  

arrayW[1] = arrayB[1] + arrayD[1];

arrayW[2] = arrayB[2] + arrayD[2];

Thanks in advance; I have no idea what I'm doing (both in assembly and on SO, so sorry about that).

Upvotes: 5

Views: 13054

Answers (3)

Michael
Michael

Reputation: 58487

You can zero-extend (unsigned) and sign-extend (signed) bytes/words to words/dwords using the MOVZX and MOVSX instructions.

For example:

movzx ax,byte [arrayB + 0]  ; ax becomes 0x00AA (== 170)
movsx ebx,byte [arrayB + 0] ; ebx becomes 0xFFFFFFAA (== -86)

To narrow a value from dword to word you can simply grab the lower word. Keep in mind that if the dword contains non-zero bits in its upper word you'll lose that information (that's not a problem with the values you posted in your question though; they all fit in 16 bits):

mov ax,word [arrayD + 4]    ; put the lower word of the 2nd dword in ax

Upvotes: 3

johnfound
johnfound

Reputation: 7061

It is pretty simple task, but there are some tiny moments. At first, if you want to convert bigger data type to smaller, you should ensure, that the values are small enough to fit in the smaller type variable. In your case, it is "word" and all numbers are small enough to fit in two bytes.

The second problem is the sign of the numbers. Are they signed, or unsigned? In the example, there are only positive numbers, but you should make it clear in the common case.

Converting from smaller to higher variable size is pretty straightforward, you should use movzx for unsigned variables or movsx for signed.

Converting from bigger to smaller data size is even simpler. You simply should use the lower part of the number and to ignore the higher part.

Here is simple implementation (FASM syntax):

    movsx  ax, [arrayB]          ; it is arrayB[0]
    add    ax, word [arrayD]     ; it is the lower word of arrayD[0]
    mov    [arrayW], ax          ; it is arrayW[0]

    movsx  ax, [arrayB+1]        ; arrayB[1]
    add    ax, word [arrayD+4]   ; arrayD[1] - note the array element size is 4 bytes long.
    mov    [arrayW+2], ax        ; arrayW[1] - array element size is 2 bytes.

    movsx  ax, [arrayB+2]        ; arrayB[2]
    add    ax, word [arrayD+8]   ; arrayD[2] 
    mov    [arrayW+4], ax        ; arrayW[2] 

Upvotes: 1

Frank Kotler
Frank Kotler

Reputation: 3119

I think a high-level language would whine piteously about this. (but who cares what a HLL does?) You are quite correct to be nervous about converting a doubleword to a word. You can't do it, in general, without losing information. In this case, we can see by inspection that all three numbers in the doubleword array will fit into words, so you can just truncate them and call it "converted" I guess. (terrible assignment, IMHO)

What may give you more trouble is addressing arrays of three different sizes. Index 0 is easy. But for index 1, you need to get a byte from [arrayB + 1], add it to a doubleword truncated down to a word from [arrayD + 4], and store the resulting word in [arrayW + 2]. You can probably figure out what index 2 is going to look like. You say you know how to do the byte to word part, so you know if you do `mov ax, [ArrayB]' it's going to get both 170 and 193, right?

Give it a shot and come back if you have problems with your code.

Upvotes: 3

Related Questions