Crusader158
Crusader158

Reputation: 21

Big Endian to Little Endian

My original assignment question is this:

Write a program that uses the variables below and MOV instructions to copy the value from bigEndian to littleEndian, reversing the order of the bytes. The number's 32 - bit value is understood to be 12345678 hexadecimal.

.data
bigEndian   BYTE 12h, 34h, 56h, 78h
littleEndian DWORD?

I think my code is right but I can't figure out why I am getting this error. Here's my code and error:

.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD

.data
 bigEndian   BYTE 12h, 34h, 56h, 78h
 littleEndian DWORD ?
 .code
 main PROC
 mov eax, DWORD PTR bigEndian; eax = 87654321h
 mov littleEndian, eax

 invoke ExitProcess, 0
 main ENDP
 END main

1>------ Build started: Project: BigEndianLittleEndian, Configuration: Debug Win32 ------

1> Assembling BigEndiantoLittleEndian.asm...

1>BigEndiantoLittleEndian.asm(20): error A2008: syntax error

1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\BuildCustomizations\masm.targets(50,5): error MSB3721: The command "ml.exe /c /nologo /Zi /Fo"Debug\BigEndiantoLittleEndian.obj" /W3 /errorReport:prompt /TaBigEndiantoLittleEndian.asm" exited with code 1.

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

How can I fix this error?

Here is updated code:

.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD

.data
bigEndian   BYTE 12h, 34h, 56h, 78h
littleEndian DWORD ?


.code
main PROC

mov ah, byte ptr bigEndian+0
mov al, byte ptr bigEndian+1
mov word ptr littleEndian+2,ax;here I want to move my now full register into      the 32bit register eax. 
mov ah, byte ptr bigEndian+2
mov al, byte ptr bigEndian+3
mov word ptr littleEndian+2,ax here I want to move my now full register into    the 32bit register eax which results in the order being reversed.


invoke ExitProcess, 0
main ENDP
END main

The error I get

1>------ Build started: Project: BigEndianLittleEndian, Configuration: Debug Win32 ------

1> Assembling BigEndiantoLittleEndian.asm...

1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppCommon.targets(708,9): error MSB4030: "main" is an invalid value for the "NoEntryPoint" parameter of the "Link" task. The "NoEntryPoint" parameter is of type "System.Boolean".

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Upvotes: 0

Views: 15587

Answers (4)

Nick S
Nick S

Reputation: 9

I actually just had this exact same assignment, thought i would post my answer here. There IS a way to swap the bytes around by taking advantage of pointers and the OFFSET command. LittleEndian is only applied when writing bytes to memory. Which means when you run the following code, eax will hold the reversed bytes of bigEndian.

LittleEndian <=> BigEndian

mov ebx,OFFSET bigEndian
mov eax, [ebx]

This assignment however, restricted us to only using the mov operator. In my case, the OFFSET operators are not allowed either. Literally all we could use was mov. In light of this, you will need to swap the bytes around manually, and since you cannot move data from memory to memory, we are forced to use an 8-bit register as a buffer to temporarily hold the data.

You can access each byte of bigEndian individually by using offsets bigEndian+0 -> bigEndian+3, but considering we declared littleEndian after bigEndian, memory was allocated for littleEndian just after bigEndian. Which means if we move offsets bigEndian+4 -> bigEndian+7 we can directly access littleEndian using small 8-bit increments. I took advantage of this and used it in my code.

EDIT: Here is the final result

.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword
INCLUDE Irvine32.inc
.data

    bigEndian BYTE 12h, 34h, 56h, 78h
    littleEndian DWORD ?

.code
main proc

    ; You can swap them by taking advantage of when littleEndian is applied to variables in memory. 
    ; Since we are limited to only mov operators, we cannot use this code. But it's nice to have for the future.
    ; mov ebx,OFFSET bigEndian
    ; mov eax, [ebx]

    ; Display bigEndian
    mov ebx, 1  ;set to write eax al 8 hex digits using WriteHexB
    mov al, bigEndian+0
    call WriteHexB
    mov al, bigEndian+1
    call WriteHexB
    mov al, bigEndian+2
    call WriteHexB
    mov al, bigEndian+3
    call WriteHexB
    call CrlF

    ; Since bigEndian was declared before littleEndian, bigEndian only goes as far as bigEndian+3
    ; However, since littleEndian was declared after, we can traverse littleEndian using bigEndian+4 -> bigEndian+7.
    ; Considering we cannot move data from memory to memory, we have to use an 8-bit register as a buffer.
    ; We will use al register.

    ; bigEndian = 12345678h, littleEndian = 00000000h

    mov al, bigEndian+0
    mov bigEndian+4, al

    ; bigEndian = 12345678h, littleEndian = 00000012h

    mov al, bigEndian+1
    mov bigEndian+5, al

    ; bigEndian = 12345678h, littleEndian = 00003412h

    mov al, bigEndian+2
    mov bigEndian+6, al

    ; bigEndian = 12345678h, littleEndian = 00563412h

    mov al, bigEndian+3
    mov bigEndian+7, al

    ; bigEndian = 12345678h, littleEndian = 78563412h



    ; Write littleEndian to eax to display on screen
    mov eax, littleEndian

    ; Display littleEndian
    call WriteHex
    call CrlF

    ; Display 'Press [enter] to continue...'
    call WaitMsg

    invoke ExitProcess,0
main endp
end main    

Upvotes: 0

P. Fernandez
P. Fernandez

Reputation: 187

I came up with what seems like a better way to do solve the problem. It still sticks to the restraint of only using MOV instructions, but it doesn't destroy the array's original value.

INCLUDE Irvine32.inc

.data
bigEndian       BYTE    12h, 34h, 56h, 78h
littleEndian    DWORD   ?

.code
main            PROC
    mov esi, OFFSET bigEndian
    mov eax, 0
    mov al, [esi+3]     ;Isolate 5678h
    mov ah, [esi+2]
    mov ebx, 0
    mov bl, [esi+1]     ;Isolate 1234h
    mov bh, [esi]

    mov esi, OFFSET littleEndian
    mov [esi], eax      ;Move 5678h into lower 16bits of littleEndian
    mov [esi+2], ebx    ;Move 1234h into higher 16bits of littleEndian      
    invoke  ExitProcess, 0
main        ENDP
END main

Upvotes: 1

P. Fernandez
P. Fernandez

Reputation: 187

I just finished this in my Assembly course. Here is what I painstakingly came up with. I am almost certain that there is a better, and more correct way to do it, but this was the only way that I could figure it out. Haven't turned it in for a grade yet, so I don't know how well it well hold up in that aspect. I suspect it will be fine. It does what the problem requested, within the constraints set.

 ; Description:  Copy value from bigEndian to littleEndian, reversing order of bytes
 ; Assignment: A06B 4.10 Programming Exercise
 ; Date: 3/17/2016

INCLUDE Irvine32.inc

.data
bigEndian       BYTE            12h, 34h, 56h, 78h
littleEndian    DWORD           ?

.code
main            PROC
                mov     al, [bigEndian+3]       ;swap 78h and 12h
                mov     ah, [bigEndian]     
                mov     [bigEndian], al
                mov     [bigEndian+3], ah

                mov     al, [bigEndian+2]       ;swap 56h and 34h
                mov     ah, [bigEndian+1]
                mov     [bigEndian+1], al
                mov     [bigEndian+2], ah

                mov     eax, DWORD PTR bigEndian    ;move reverse ordered bytes to eax
                mov     littleEndian, eax       ;move reverse ordered byted to littleEndian
                invoke  ExitProcess, 0
main            ENDP
END main

Upvotes: 1

lvd
lvd

Reputation: 812

You should actually swap bytes in eax before writing it back to memory:

mov   eax,DWORD PTR bigEndian
bswap eax
mov   littleEndian,eax

By using exclusively mov instructions it could be like this:

mov al,DWORD PTR bigEndian+0
mov ah,DWORD PTR bigEndian+1
mov bl,DWORD PTR bigEndian+2
mov bh,DWORD PTR bigEndian+3

mov littleEndian+0,bh
mov littleEndian+1,bl
mov littleEndian+2,ah
mov littleEndian+3,al

Upvotes: 5

Related Questions