2015-05-11 5 views
0

В настоящее время я пытаюсь изучить сборку (Intel x86), и я создал программу, которая имитирует битовую начинку на 32-битных словах -> каждые 5 последовательных идентичных бит (5 0 или 5 1) вставлен противоположный бит. Чтобы сохранить слово до его первоначального 32-битного размера, менее значимые биты усекаются, если добавляются биты добавления.Bitstuffing в сборе не работает по назначению

Вот несколько примеров:

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 

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

+1

Мы не являемся сервисом отладки. Что именно вы не понимаете? Какой у Вас вопрос? –

+0

@DwayneTowell Извините o.o Я довольно устал и забыл опубликовать конкретные проблемы. Я немедленно отредактирую его – Iocust

+1

Обратите внимание, что стандартное соглашение о вызове C не позволяет уничтожать 'ebx'. Тем не менее, это может иметь или не иметь ничего общего с вашей непосредственной проблемой. Вы должны добавить 'push ebx/pop ebx' вокруг вашего кода. – Jester

ответ

1

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

in operation at ideone.com Посмотри.

+0

Я вижу! Хотя я не вижу способа сделать это иначе. Возможно, использование масок поможет? У меня нет опыта с ними, но – Iocust

+0

Подход с поворотом на место делает его трудным. Вы можете просто использовать отдельные регистры ввода и вывода, а затем вы можете легко набить свой бит. См. Обновленный ответ для возможного решения. – Jester

+1

Большое спасибо! Кажется, это то, что я ищу, хотя, признаюсь, я бы не подумал сделать так. Ура! – Iocust

Смежные вопросы