汇编中的位填充未按预期工作
Bitstuffing in assembly not working as intended
我目前正在尝试学习汇编 (Intel x86),并且我制作了一个程序来模拟 32 位字上的位填充 -> 每 5 个连续的相同位(5 个 0 或 5 个 1),插入一个相反的位.为了使字保持其原始的 32 位大小,如果添加填充位,则对较低有效位进行处理 运行。
这里有几个例子:
0000 1111 0000 1111 0000 1111 0000 1111 -> 0000 1111 0000 1111 0000 1111 0000 1111
0000 1111 0000 1111 0000 1111 0000 0000 -> 0000 1111 0000 1111 0000 1111 0000 0100
0000 1111 0000 1111 0000 0000 0000 0000 -> 0000 1111 0000 1111 0000 0100 0001 0000
所以这是我的 C++ 程序,它测试是否一切正常,但最后两个不工作,我不明白为什么。我 运行 通过使用 IDE 调试器跟踪程序执行的每个步骤多次,它似乎完全按照我想要的方式执行,但结果不符合...
#include <iostream>
using namespace std;
extern "C" {unsigned int bitstuffing(unsigned int a);}
int main () {
unsigned int in = 0xFFFFFFFF;
unsigned int verif = 0xFBEFBEFB;
unsigned int out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0x00000000;
verif = 0x04104104;
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0xF0F0F0F; // 0000 1111 0000 1111 0000 1111 0000 1111
verif = 0xF0F0F0F; // 0000 1111 0000 1111 0000 1111 0000 1111
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0xF0F0F00; // 0000 1111 0000 1111 0000 1111 0000 0000
verif = 0xF0F0F04; // 0000 1111 0000 1111 0000 1111 0000 0100
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0xF0F0000; // 0000 1111 0000 1111 0000 0000 0000 0000
verif = 0xF0F0410; // 0000 1111 0000 1111 0000 0100 0001 0000
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0xAAAA0000; // 1010 1010 1010 1010 0000 0000 0000 0000
verif = 0xAAAA0820; // 1010 1010 1010 1010 0000 1000 0010 0000
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0x7878000; // 0000 0111 1000 0111 1000 0000 0000 0000
verif = 0x7C1F041; // 0000 0111 1100 0001 1111 0000 0100 0001
// out = 0000 0111 1100 0111 1101 0000 0100 0001
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
return 0;
}
这是最重要的ASM程序
CPU 386
%include "io.inc"
section .text
global CMAIN
;0FFFFFFFFh - 0xFBEFBEFB ok
;000000000h - 0x04104104 ok
;0F0F0F0Fh - 0xF0F0F0F ok
;0F0F0F00h - 0xF0F0F04 ok
;0F0F0000h - 0xF0F0410 ok
;0AAAA0000h - 0xAAAA0820 DOESNT WORK
;07878000h - 0x7878000 DOESNT WORK
CMAIN:
mov ebp, esp; for correct debugging
PUSH EBP
MOV EBP, ESP
MOV EAX, 07878000h;[EBP+8] ; places message (parameter) in EAX
MOV ECX, 32
MOV BL, 0 ; counts number of "0" bits
MOV BH, 0 ; counts number of "1" bits
loop1:
ROL EAX, 1
JC carry
JNC no_carry
carry:
XOR BL, BL ; resets "0" counter to 0
INC BH ; increments "1" counter
CMP BH, 5 ; if we get 5 consecutive bits of the same sign -> bitstuffing
JE stuffing_0
DEC ECX ; Decrementing ECX for loop
JNZ loop1
JZ end
no_carry:
XOR BH, BH ; resets "1" counter to 0
INC BL ; increments "0" counter
CMP BL, 5 ; if we get 5 consecutive bits of the same sign -> bitstuffing
JE stuffing_1
DEC ECX ; Decrementing ECX for loop
JNZ loop1
JZ end
stuffing_0:
XOR EDX, EDX
XOR EBX, EBX
MOV EDX, 2 ; Putting 2 in EDX for MUL operation
MUL EDX ; Multiplying EAX by 2 is like adding a 0 at the end
XOR EDX, EDX ; Resetting EDX register
DEC ECX ; Decrementing ECX twice for loop (in order to truncate bits)
DEC ECX
CMP ECX, 0
JG loop1
JLE end
stuffing_1:
XOR EDX, EDX
XOR EBX, EBX
MOV EDX, 2 ; Putting 2 in EDX for MUL operation
MUL EDX ; Multiplying EAX by 2 is like adding a 0 at the end
ADD EAX, 1 ; Adding 1 to EAX when the last bit is the zero we added is the same is adding 1 instead of zero
XOR EDX, EDX ; Resetting EDX register
DEC ECX ; Decrementing ECX twice for loop (in order to truncate bits)
DEC ECX
CMP ECX, 0
JG loop1
JLE end
end:
LEAVE
RET
所以当我运行这个程序时,它使用以下值工作得很好(它们都放在EAX中)
;0FFFFFFFFh - 0xFBEFBEFB ok
;000000000h - 0x04104104 ok
;0F0F0F0Fh - 0xF0F0F0F ok
;0F0F0F00h - 0xF0F0F04 ok
;0F0F0000h - 0xF0F0410 ok
但不适用于以下
;0AAAA0000h - 0xAAAA0820 DOESNT WORK
;07878000h - 0x7878000 DOESNT WORK
如果有人能发现问题,那将会很有帮助!
要填充新位,请乘以 2
,这只是左移的一种复杂方法。这将丢弃最高有效位,因此您不是从原始值的最低有效位置开始丢弃,而是基本上用填充位覆盖以下位。
简而言之,您的代码并不像您所说的那样:)
可能的解决方案(gas
语法):
.intel_syntax noprefix
.global main
main:
sub esp, 12
mov [esp + 8], ebx
xor ebx, ebx
test_loop:
mov eax, [in + 4 * ebx]
mov dword ptr [esp], eax
call bitstuffing
mov [esp + 8], eax
cmp eax, [verify + 4 * ebx]
mov dword ptr [esp], offset ok
je got_fmt
mov dword ptr [esp], offset error
got_fmt:
mov eax, [in + 4 * ebx]
mov [esp + 4], eax
call printf
inc ebx
cmp ebx, 7
jb test_loop
mov ebx, [esp + 8]
add esp, 12
xor eax, eax
ret
bitstuffing:
push ebp
mov ebp, esp
push ebx
mov cl, 32 # 32 bits to go
xor eax, eax # the output
mov edx, [ebp + 8] # the input
xor bl, bl # the run count
next_bit:
dec cl # more bits?
js done # no
shl edx, 1 # consume from the input into CF
rcl eax, 1 # copy to output from CF
test bl, bl # first bit always matches
jz match
test al, 3 # do we have 00 or 11 in the low 2 bits?
jnp reset # no, start counting again
match:
inc bl
cmp bl, 5 # did 5 bits match?
jb next_bit # no, keep going
dec cl # space for stuffed bit?
js done # no
mov ebx, eax # make a copy
and ebx, 1 # isolate LSB
xor ebx, 1 # flip it
shl eax, 1 # make space for it
or eax, ebx # stuff it
reset:
mov bl, 1 # already have length 1
jmp next_bit
done:
pop ebx
mov esp, ebp
pop ebp
ret
.data
ok: .string "OK: 0x%08x => 0x%08x\n"
error: .string "ERROR: 0x%08x => 0x%08x\n"
in: .int 0xFFFFFFFF, 0x00000000, 0x0F0F0F0F, 0x0F0F0F00, 0x0F0F0000, 0xAAAA0000, 0x07878000
verify: .int 0xFBEFBEFB, 0x04104104, 0x0F0F0F0F, 0x0F0F0F04, 0x0F0F0410, 0xAAAA0820, 0x07C1F041
我目前正在尝试学习汇编 (Intel x86),并且我制作了一个程序来模拟 32 位字上的位填充 -> 每 5 个连续的相同位(5 个 0 或 5 个 1),插入一个相反的位.为了使字保持其原始的 32 位大小,如果添加填充位,则对较低有效位进行处理 运行。
这里有几个例子:
0000 1111 0000 1111 0000 1111 0000 1111 -> 0000 1111 0000 1111 0000 1111 0000 1111
0000 1111 0000 1111 0000 1111 0000 0000 -> 0000 1111 0000 1111 0000 1111 0000 0100
0000 1111 0000 1111 0000 0000 0000 0000 -> 0000 1111 0000 1111 0000 0100 0001 0000
所以这是我的 C++ 程序,它测试是否一切正常,但最后两个不工作,我不明白为什么。我 运行 通过使用 IDE 调试器跟踪程序执行的每个步骤多次,它似乎完全按照我想要的方式执行,但结果不符合...
#include <iostream>
using namespace std;
extern "C" {unsigned int bitstuffing(unsigned int a);}
int main () {
unsigned int in = 0xFFFFFFFF;
unsigned int verif = 0xFBEFBEFB;
unsigned int out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0x00000000;
verif = 0x04104104;
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0xF0F0F0F; // 0000 1111 0000 1111 0000 1111 0000 1111
verif = 0xF0F0F0F; // 0000 1111 0000 1111 0000 1111 0000 1111
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0xF0F0F00; // 0000 1111 0000 1111 0000 1111 0000 0000
verif = 0xF0F0F04; // 0000 1111 0000 1111 0000 1111 0000 0100
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0xF0F0000; // 0000 1111 0000 1111 0000 0000 0000 0000
verif = 0xF0F0410; // 0000 1111 0000 1111 0000 0100 0001 0000
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0xAAAA0000; // 1010 1010 1010 1010 0000 0000 0000 0000
verif = 0xAAAA0820; // 1010 1010 1010 1010 0000 1000 0010 0000
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
in = 0x7878000; // 0000 0111 1000 0111 1000 0000 0000 0000
verif = 0x7C1F041; // 0000 0111 1100 0001 1111 0000 0100 0001
// out = 0000 0111 1100 0111 1101 0000 0100 0001
out = bitstuffing(in);
if (out==verif) cout<<endl<<"OK: "<<hex<<out<<dec<<endl;
else cout<<endl<<"ERROR: "<<hex<<out<<dec<<endl;
return 0;
}
这是最重要的ASM程序
CPU 386
%include "io.inc"
section .text
global CMAIN
;0FFFFFFFFh - 0xFBEFBEFB ok
;000000000h - 0x04104104 ok
;0F0F0F0Fh - 0xF0F0F0F ok
;0F0F0F00h - 0xF0F0F04 ok
;0F0F0000h - 0xF0F0410 ok
;0AAAA0000h - 0xAAAA0820 DOESNT WORK
;07878000h - 0x7878000 DOESNT WORK
CMAIN:
mov ebp, esp; for correct debugging
PUSH EBP
MOV EBP, ESP
MOV EAX, 07878000h;[EBP+8] ; places message (parameter) in EAX
MOV ECX, 32
MOV BL, 0 ; counts number of "0" bits
MOV BH, 0 ; counts number of "1" bits
loop1:
ROL EAX, 1
JC carry
JNC no_carry
carry:
XOR BL, BL ; resets "0" counter to 0
INC BH ; increments "1" counter
CMP BH, 5 ; if we get 5 consecutive bits of the same sign -> bitstuffing
JE stuffing_0
DEC ECX ; Decrementing ECX for loop
JNZ loop1
JZ end
no_carry:
XOR BH, BH ; resets "1" counter to 0
INC BL ; increments "0" counter
CMP BL, 5 ; if we get 5 consecutive bits of the same sign -> bitstuffing
JE stuffing_1
DEC ECX ; Decrementing ECX for loop
JNZ loop1
JZ end
stuffing_0:
XOR EDX, EDX
XOR EBX, EBX
MOV EDX, 2 ; Putting 2 in EDX for MUL operation
MUL EDX ; Multiplying EAX by 2 is like adding a 0 at the end
XOR EDX, EDX ; Resetting EDX register
DEC ECX ; Decrementing ECX twice for loop (in order to truncate bits)
DEC ECX
CMP ECX, 0
JG loop1
JLE end
stuffing_1:
XOR EDX, EDX
XOR EBX, EBX
MOV EDX, 2 ; Putting 2 in EDX for MUL operation
MUL EDX ; Multiplying EAX by 2 is like adding a 0 at the end
ADD EAX, 1 ; Adding 1 to EAX when the last bit is the zero we added is the same is adding 1 instead of zero
XOR EDX, EDX ; Resetting EDX register
DEC ECX ; Decrementing ECX twice for loop (in order to truncate bits)
DEC ECX
CMP ECX, 0
JG loop1
JLE end
end:
LEAVE
RET
所以当我运行这个程序时,它使用以下值工作得很好(它们都放在EAX中)
;0FFFFFFFFh - 0xFBEFBEFB ok
;000000000h - 0x04104104 ok
;0F0F0F0Fh - 0xF0F0F0F ok
;0F0F0F00h - 0xF0F0F04 ok
;0F0F0000h - 0xF0F0410 ok
但不适用于以下
;0AAAA0000h - 0xAAAA0820 DOESNT WORK
;07878000h - 0x7878000 DOESNT WORK
如果有人能发现问题,那将会很有帮助!
要填充新位,请乘以 2
,这只是左移的一种复杂方法。这将丢弃最高有效位,因此您不是从原始值的最低有效位置开始丢弃,而是基本上用填充位覆盖以下位。
简而言之,您的代码并不像您所说的那样:)
可能的解决方案(gas
语法):
.intel_syntax noprefix
.global main
main:
sub esp, 12
mov [esp + 8], ebx
xor ebx, ebx
test_loop:
mov eax, [in + 4 * ebx]
mov dword ptr [esp], eax
call bitstuffing
mov [esp + 8], eax
cmp eax, [verify + 4 * ebx]
mov dword ptr [esp], offset ok
je got_fmt
mov dword ptr [esp], offset error
got_fmt:
mov eax, [in + 4 * ebx]
mov [esp + 4], eax
call printf
inc ebx
cmp ebx, 7
jb test_loop
mov ebx, [esp + 8]
add esp, 12
xor eax, eax
ret
bitstuffing:
push ebp
mov ebp, esp
push ebx
mov cl, 32 # 32 bits to go
xor eax, eax # the output
mov edx, [ebp + 8] # the input
xor bl, bl # the run count
next_bit:
dec cl # more bits?
js done # no
shl edx, 1 # consume from the input into CF
rcl eax, 1 # copy to output from CF
test bl, bl # first bit always matches
jz match
test al, 3 # do we have 00 or 11 in the low 2 bits?
jnp reset # no, start counting again
match:
inc bl
cmp bl, 5 # did 5 bits match?
jb next_bit # no, keep going
dec cl # space for stuffed bit?
js done # no
mov ebx, eax # make a copy
and ebx, 1 # isolate LSB
xor ebx, 1 # flip it
shl eax, 1 # make space for it
or eax, ebx # stuff it
reset:
mov bl, 1 # already have length 1
jmp next_bit
done:
pop ebx
mov esp, ebp
pop ebp
ret
.data
ok: .string "OK: 0x%08x => 0x%08x\n"
error: .string "ERROR: 0x%08x => 0x%08x\n"
in: .int 0xFFFFFFFF, 0x00000000, 0x0F0F0F0F, 0x0F0F0F00, 0x0F0F0000, 0xAAAA0000, 0x07878000
verify: .int 0xFBEFBEFB, 0x04104104, 0x0F0F0F0F, 0x0F0F0F04, 0x0F0F0410, 0xAAAA0820, 0x07C1F041