Битовые заготовки в сборке не работают должным образом

В настоящее время я пытаюсь изучить ассемблер (Intel x86), и я создал программу, которая имитирует битовую вставку 32-битных слов -> каждые 5 последовательных идентичных бит (5 или 5), вставляется противоположный бит. Чтобы сохранить слово в его первоначальном 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 WORKCMAIN:
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

Если кто-то может определить проблему, это будет очень полезно!

0

Решение

Чтобы набить новый бит, вы умножаете на 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

Видеть это в работе на ideone.com.

1

Другие решения


По вопросам рекламы [email protected]