【问题标题】:convert x86 to x86-64 assembly将 x86 转换为 x86-64 程序集
【发布时间】:2014-08-07 14:02:51
【问题描述】:

不幸的是,我明天正在为我的计划而苦苦挣扎。我应该为 x86 和 x86-x64 平台编写程序集旋转 24bpp 方形 bmp 图像。 用于 32 位处理器的 x86 版本工作正常,但我在将其转换为 64 位时遇到问题。

  • 程序可以编译,但在执行过程中出现分段错误,因为我无法调试它,所以很难猜测问题出在哪里。

编译代码: nasm -f elf64 rot64.asm && cc -m64 -o project64 project.c rot64.o && ./project64 picture.bmp

  • c 中的代码通过调用将纯位图(不带标题)传递给组件部分:void rotbmp24(void *r9, int width)

下面我放了 32 位处理器的工作代码,而不是 64 位的工作代码:

32位版本:

; void rotbmp24(void *img, int width);
;  Rotate a 24 bpp square .BMP image of any size 90 degrees clockwise.

global rotbmp24

;define addresses of parameters passed by caller
%define     img         [ebp+8]     ;pointer to bmp image   
%define     width       [ebp+12]    ;address of width   
; allocation of place in memory for local variables
%define     row_bytes   [ebp-4]
%define     img_line    [ebp-8]
%define     img_collumn     [ebp-12]
%define     img_width       [ebp-16]

rotbmp24:
; making stack frame
push    ebp
mov     ebp, esp
sub     esp, 16

; prologue
push    ebx
push    esi
push    edi

; calculate row size
mov     eax, width       ; row size in pixels
mov     edx, eax        ;preserve eax
imul    edx, 3      ; row size* in bytes (3 bytes per pixel)
add     edx, 3      ; 3 is the maximum value to fit on 2 least sign. bits
and     edx, 0fffffffch ; zero out 2 least sign. bits, to round up to multiple of 4
mov     row_bytes, edx  ; row size in bytes (multiple of 4)

; img_width variable is now width of our bmp image
mov     img_width, eax

; pixel line    
mov     esi, img
mov     img_line, esi

; pixel collumn
sub     eax, 1
mov     edi, eax        ;preserve eax
imul    edi, 3      ; row size* in bytes (3 bytes per pixel)
mul     dword row_bytes     ; eax=eax* (row_bytes, set to 32b)
add     edi, img
add     edi, eax
mov     img_collumn, edi    ;last row

changebyte:
; change rows into collumns
mov     eax, [esi]  ;first element
mov     edx, [edi]  ;last row element

mov     ebx, eax    ;duplicate them
mov     ecx, edx

and     eax, 00ffffffh  ;check if given bits are...
and     edx, 00ffffffh
and     ebx, 0ff000000h
and     ecx, 0ff000000h

or      eax, ecx    ;put bits together
or      edx, ebx

mov     [edi], eax  ;change of elementst
mov     [esi], edx    

add     esi, 3  ;move to next byte from first
sub     edi, row_bytes  ;move to next element from last
cmp     edi, esi    ;if they are equal then we finished outer lines
jne     changebyte  
;we proceed with next lines&collumns
mov     esi, img_line
add     esi, row_bytes
mov     img_line, esi
mov     edi, img_collumn    
sub     edi, 3
mov     img_collumn, edi

cmp     edi, esi
jne     changebyte

; eeax is again width of pixel array
mov     eax, width
mov     img_width, eax

mov     esi, img
mov     img_line, esi

settt:
mov     eax, width    
sub     eax, 1
lea     edi, [eax+eax*2]
add     edi, esi

invertbyte:
; horizontal mirror
mov     eax, [esi]
mov     edx, [edi]

mov     ebx, eax
mov     ecx, edx

and     eax, 00ffffffh
and     edx, 00ffffffh
and     ebx, 0ff000000h
and     ecx, 0ff000000h

or      eax, ecx
or      edx, ebx
;changing one lines
mov     [edi], eax
mov     [esi], edx    
add     esi, 3
sub     edi, 3

cmp     edi, esi
ja      invertbyte
;jump to next lines
mov     esi, img_line
add     esi, row_bytes
mov     img_line, esi

mov     ecx, img_width
dec     ecx
mov     img_width, ecx
jnz     settt

; epilogue
pop     edi
pop     esi
pop     ebx

; return to caller        
mov     esp, ebp
pop     ebp
ret

64位处理器代码:

; 17. void rotbmp24(void *r9, int width);
;  Rotate a 24 bpp square .BMP image of any size 90 degrees clockwise.
;section .data
;message:
;   db 'Hello, World', 10, 0
    
;global rotbmp24
;section .text
;define addresses of parameters passed by caller
;rdi - r9  img        [rbp+8]       pointer to bmp image    
;rsi - r10    width       [rbp+12]  ;address of width   
; allocation of place in memory for local variables
;r11     row_bytes   [rbp-4]
;r12     r9_line    [rbp-8]
;r13     r9_collumn     [rbp-12]
;r14     r9_width       [rbp-16]
 
rotbmp24:
    ; making stack frame
push    rbp
mov     rbp, rsp
;sub     rsp, 16

; prologue
push    rbx
push    rsi 
push    r9
push    r10
push    r11
push    r12
push    r14
push    r15
mov     r9, rdi
mov     r10, [rsi]

  ; calculate row size
    mov     rax, r10     ; row size in pixels
mov     edx, r10d       ;preserve rax
imul    edx, 3      ; row size* in bytes (3 bytes per pixel)
add     edx, 3      ; 3 is the maximum value to fit on 2 least sign. bits
and     edx, 0xfffffffc ; zero out 2 least sign. bits, to round up to multiple of 4
mov     r11d, edx   ; row size in bytes (multiple of 4)

; r14 variable is now width of our bmp image
mov     r14, rax

; pixel line    
mov     rsi, r9
mov     r12, rsi

; pixel collumn
sub     rax, 1
mov     rdi, rax        ;preserve rax
imul    rdi, 3      ; row size* in bytes (3 bytes per pixel)
mul     qword r11       ; rax=rax* (r11, set to 32b)
add     rdi, r9
add     rdi, rax
mov     r13, rdi    ;last row


;mov rdi, message ; rdi gets the first argument (a pointer)
;xor rax, rax call
;ret printf ; printf has a variable number of arguments,
; so rax needs to be set to the number of
; vector registers used...zero in this case


changebyte:
; change rows into collumns
mov     eax, [rsi]  ;first element
mov     edx, [rdi]  ;last row element

mov     ecx, eax    ;duplicate them
mov     r15d, edx

and     eax,  00ffffffh ;get 24  bits and leave rest untouched
and     edx,  00ffffffh
and     ecx, 0ff000000h
and     r15d, 0ff000000h

or      eax, r15d   ;put bits together
or      edx, ecx

mov     [rdi], eax  ;change of elements
mov     [rsi], edx    

add     rsi, 3  ;move to next byte from first
sub     rdi, r11    ;move to next element from last
cmp     rdi, rsi    ;if they are equal then we finished outer lines
jne     changebyte  
;we proceed with next lines&collumns
mov     rsi, r12
add     rsi, r11
mov     r12, rsi
mov     rdi, r13    
sub     rdi, 3
mov     r13, rdi

cmp     rdi, rsi
jne     changebyte

; erax is again width of pixel array
mov     rax, r10
mov     r14, rax

mov     rsi, r9
mov     r12, rsi

settt:
mov     rax, r10    
sub     rax, 1
lea     rdi, [rax+rax*2]
add     rdi, rsi

invertbyte:
; horizontal mirror
mov     eax, [r9]
mov     edx, [rdi]

mov     ecx, eax
mov     r15d, edx

and     eax, 00ffffffh
and     edx, 00ffffffh
and     ecx, 0ff000000h
and     r15d, 0ff000000h

or      eax, r15d
or      edx, ecx
;changing one lines
mov     [rdi], eax
mov     [rsi], edx    
add     rsi, 3
sub     rdi, 3

cmp     rdi, rsi
ja      invertbyte
;jump to next lines
mov     rsi, r12
add     rsi, r11
mov     r12, rsi

mov     r15d, r14d
dec     r15d
mov     r14d, r15d
jnz     settt

; epilogue
pop    rbp
mov     rbp, rsp
sub     rsp, 16


pop     r15
pop     r14
pop     r12
pop     r11
pop     r10
pop     r9

pop    rsi  
pop    rbx
; return to caller        
mov     rsp, rbp
pop     rbp
ret

【问题讨论】:

  • 为什么不能准确调试?
  • 我真的不知道该怎么做。我正在使用 NAsm 模拟器,但找不到调试它的方法。
  • nasm 不是模拟器,而是汇编器。您应该在开始编写代码之前就学会使用调试器。
  • 好的,我明白了。但我不知道如何使用控制台调试器。这对我来说似乎是黑魔法。汇编程序不是我最好的网站。你能帮我找出错误吗?

标签: assembly x86 64-bit x86-64 nasm


【解决方案1】:

mov r10, [rsi] 应该只是 mov r10, rsi,因为 rsi 有宽度,而不是指针。

标签epilogue处的三行应删除。

通过这些更改,我尝试过的测试用例不会崩溃。

你真的应该学会调试自己。

【讨论】:

  • 谢谢 :) 现在运行没有错误。现在它削减了上半部分,只翻译了底部,但我已经考虑过改变并尝试解决这个问题。你用的是什么调试的?我必须学习它:)
  • 现在可以使用了!!!再次非常感谢。如果我有 15 个徽章,我会提出你的答案:) 我只改变了一件额外的事情。无论如何,我应该学习调试器:)
猜你喜欢
  • 2018-03-30
  • 1970-01-01
  • 2012-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多