Big Endian到Little Endian

时间:2016-03-01 01:50:29

标签: assembly x86 masm 32-bit

我的原始作业问题是:

  

编写一个程序,使用下面的变量和MOV指令将值从bigEndian复制到littleEndian,反转字节的顺序。数字的32位值被理解为12345678十六进制。

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

我认为我的代码是正确的,但我无法弄清楚为什么我会收到此错误。这是我的代码和错误:

.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 build:Project:BigEndianLittleEndian,配置:Debug Win32 ------

     

1>组装BigEndiantoLittleEndian.asm ......

     

1> BigEndiantoLittleEndian.asm(20):错误A2008:语法错误

     

1> C:\ Program Files(x86)\ MSBuild \ Microsoft.Cpp \ v4.0 \ V140 \ BuildCustomizations \ masm.targets(50,5):错误MSB3721:命令“ml.exe / c / nologo / Zi /Fo"Debug\BigEndiantoLittleEndian.obj“/ W3 / errorReport:prompt /TaBigEndiantoLittleEndian.asm”退出,代码为1。

     

==========构建:0成功,1失败,0最新,0跳过==========

如何解决此错误?

  

这是更新的代码:

.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

我得到的错误

  

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

     

1>组装BigEndiantoLittleEndian.asm ......

     

1> C:\ Program Files(x86)\ MSBuild \ Microsoft.Cpp \ v4.0 \ V140 \ Microsoft.CppCommon.targets(708,9):错误MSB4030:“main”是“for”的无效值NoEntryPoint“链接”任务的参数。 “NoEntryPoint”参数的类型为“System.Boolean”。

     

==========构建:0成功,1失败,0最新,0跳过==========

4 个答案:

答案 0 :(得分:3)

你应该在eax之前交换字节,然后再将其写回内存:

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

完全使用mov指令可能是这样的:

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

答案 1 :(得分:1)

我刚刚在我的装配课程中完成了这个。这是我辛苦提出的。我几乎可以肯定,有一种更好,更正确的方法,但这是我能想出来的唯一方法。 Haven尚未将其转入等级,因此我不知道它在这方面的表现如何。我怀疑它会好的。它在约束集中执行问题请求。

 ; 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

答案 2 :(得分:1)

我提出了解决问题的更好方法。它仍然坚持只使用MOV指令的约束,但它不会破坏数组的原始值。

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

答案 3 :(得分:0)

我实际上只是完成了同样的任务,我想我会在这里发布我的答案。有一种方法可以通过利用指针和OFFSET命令来交换字节。 LittleEndian仅在将字节写入内存时应用。这意味着当您运行以下代码时,eax将保留bigEndian的反转字节。

LittleEndian< =>大尾端

mov ebx,OFFSET bigEndian
mov eax, [ebx]

然而,这个赋值仅限于使用mov运算符。就我而言,也不允许使用OFFSET运算符。我们可以使用的所有内容都是mov。鉴于此,您需要手动交换字节,并且由于无法将数据从内存移动到内存,因此我们不得不使用8位寄存器作为缓冲区来临时保存数据。

您可以使用偏移bigEndian + 0 - >单独访问bigEndian的每个字节。 bigEndian + 3,但考虑到我们在bigEndian之后宣布了littleEndian,内存是在bigEndian之后为littleEndian分配的。这意味着如果我们移动偏移bigEndian + 4 - > bigEndian + 7我们可以使用小的8位增量直接访问littleEndian。我利用了这个并在我的代码中使用它。

编辑:这是最终结果

.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