2016-03-21 18 views
0

Bu derleme programı bir Fizz oyunudur. Çocuk sayma oyunu için kurallara uymalıdır. Fizz: 1-100 arası ve sayı 5 ile eşit olarak bölünebiliyorsa veya rakam 5'i içeriyorsa, sayıyı “Fizz” kelimesiyle değiştirin.Montaj Programı: Fizz Oyunu

Şu anda bu programla ilgili bir sorun yaşıyorum. Program çalışır ancak çıktı: numarası = 1 Segmentasyon hatası (çekirdek bırakılmış) Birisi bana bu konuda yardımcı olabilirse memnun olurum. Eğer bir işlev çağrısı sırasında değişen ECX için hesap edilir ve dengesiz itme/pop oluyor çünkü teşekkürler

enter cextern printf 
section .data 
fmt: db "number = %d", 10, 0 ; printf format string 
fmt2: db " %s",10,0 
fmt3: db " %s ", 10, 0 
section .text 
global main 
main: 
    push ebx  ; EBX is callee saved so we need to save it so that it 
        ; it can be restored when we RETurn from main 
    xor ecx,ecx ; ebx = 0 (counter) 
L1: 
    inc ecx 
    xor eax,eax 
    mov eax,ecx 
    xor ebx,ebx 
    xor edx,edx 
    mov ebx,5 
    idiv ebx 
    cmp edx,0 
    jz Fizz 
    push ecx  ; 2nd parameter is our number to print 
    push fmt  ; 1st parameter is the address of the format string 
    call printf 

    ;add sp, 8  ; We pushed 8 bytes prior to printf call, we must adjust the stack 
        ; by effectively removing those bytes. 
      ; counter += 1 
    cmp ecx,100 
    jle L1  ; If counter is <= 100 go back and print again 
    jmp end 
Fizz: 
    mov ebx,0x4669 
    mov eax, 0x7A7A 
    push ebx 
    push eax 
    push fmt2 
    call printf 
    pop eax 
    pop ebx 

    jmp L1 
end: 
    pop ebx  ; Restore EBX before exiting main per calling convention 
    ret   ; RETurn from main will cause program to gracefully exit 
        ;  because we are linked to the C runtime code and main was 
        ;  called by that C runtime code when our program started.ode here 
+1

Bir hata ayıklayıcısında çalıştırmayı ve nerede kilitlendiğini görmeyi denediniz mi? –

+1

Bunun hakkında bir şey [tanıdık görünüyor] (http://stackoverflow.com/a/36092926/3857942) –

+0

@micheal Petch, evet o 0x080482 de çöküyor?(). Ben bilgi kayıtlarını yaparken, bu bana veren şeydir: eax 0x0 0 ecx 0x1 1 edx 0x1 1 ebx 0x5 5 ESP 0xffffd810 0xffffd810 ebp 0x0 0x0 esi 0x1 1 edi 0xf7fb3000 -134533120 eip 0xf7ff06c1 0xf7ff06c1 <_dl_runtime_resolve + 1> eflags 0x202 [IF] cs 0x23 35 ss 43 0x2b ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x63 99 (gdb) – anonymous

cevap

0

Programınız çöküyor. Burada Uyarı:

push ecx 
push fmt 
call printf 

ama asla pop bu iki değer geri yığının kapatır. ECX aramada korunmadığından ve işlev geri döndükten sonra başka bir işlem yapmıyorsanız, işlev çağrısından sonra ECX'un ne olduğuna güveniyorsunuz demektir.

calling conventions'a bakarsanız, işlev çağrılarında ecx'un korunmadığını görürsünüz. Bunu değişmeden bulabilirsiniz, ancak buna bağlı olamazsınız. Onu korumalısın.

Bu, kodun hemen end'a atlamasını ve ret'u kullanmayı denemesidir. Bu, kazasında hemen çökmesine neden oluyor, çünkü artık yığın dizesinin adresine dönmeye çalışıyorsunuz, çünkü bu, yığınının üstünde ne var?

Belki bu?

push ecx 
push fmt 
call printf 
pop ecx ; fmt 
pop ecx ; ECX 
cmp ecx, 100 
jle end 
+0

tamam, dediğin ile değiştirdim, ve çalıştırdığımda 1'den 4'e kadar olan sayılar yazdırılıyor, daha sonra bir bölütleme hatası veriyor (çekirdekli çekirdek). Bunu düzeltmek için ne yapabilirim? – anonymous

+0

Aynı ilkeleri, kodda sahip olduğunuz diğer dengesiz push/pop kombinasyonlarına da uygulayın. En az bir tane dengesiz set farkettim. –

+0

Hangisini özel olarak söyleyebilir misiniz? – anonymous