x86:访问BMP图像的未对齐像素字节

时间:2016-06-12 02:20:35

标签: image-processing assembly x86 nasm

我正在研究C + x86程序集(NASM)中的程序,该程序执行图像的旋转和缩放。为此,它逐个遍历目标图像的像素,并计算源图像中的相应像素。

汇编代码的那一部分:

; buffer operations
push ebx
fistp dword loc         ; store the number of src pixel
mov   dword ebx, loc    ; move it to ebx
imul ebx, 3             ; 3 bytes per pixel, so multiply pixel number by 3
mov dword eax, [ebx+esi]; store that pixel's color bytes ; ERROR, SEGSEV
mov dword [edi], eax    ; draw a pixel
pop ebx

特别是标记为“ERROR,SEGSEV”的行会生成分段错误。 我认为这是因为我正在尝试访问未对齐的内存地址。 也就是说,bmp文件像素缓冲区的组织方式是每个像素都有一个接一个存储的B,G,R字节,因此每个像素3个字节,每个像素的第一个字节可以在内存中有一个不能被4整除的位置(例如:像素1:0.B,1.G,2.R;像素2:3.B,4.G,5.R - 所以我必须访问地址3才能到达第二个像素)

问题是:如果我不允许访问未对齐的内存位置,那么如何访问像素的数据?在使用bmp文件时通常如何进行?

1 个答案:

答案 0 :(得分:0)

OP假设x86架构无法访问未对齐数据(地址不是所用寄存器大小的倍数),这是精简指令集计算(RISC)处理器中的常见问题。例如:

mov ebx, 0x12345677    ; Note the odd address
mov eax, [ebx]         ; Load a 32-bit register from an odd address

在像ARM或PowerPC这样的RISC架构中,这确实会导致问题:始终(ARM)或未禁用(PowerPC)。使用x86架构时,一直都可以进行未对齐的访问(虽然有时会受到速度限制) - 并且只有在486以后它才能被检查;但这项检查几乎总是关闭。

事实证明问题出在其他地方:

mov dword eax, [ebx+esi]; store that pixel's color bytes ; ERROR, SEGSEV

OP尚未确认esi保持所需的值。

但请注意,使用x86进行未对齐访问仍可能导致问题。所有段都定义为特定大小(即使该大小为4GiB)。靠近该段顶部的访问可以"溢出"段 - 和未对齐的访问是最容易受到影响的方法。