[nasm] tablica, rozmiar

RobertG

Użytkownik
Dołączył
Styczeń 3, 2007
Posty
391
Poniższy kod kompiluje pod Linuksem, kompilatorem NASM. Jego zadaniem jest zapis do tablicy cyfry 7, a następnie pobranie jej z tej tablicy i wyświetlenie na STDOUT. Chodzi mi o rozmiar myTable, tu jets on na tyle duży, ze 7ka powinna się zmieścić:

Kod:
section .text
global _start

%define mySize 10

_start:
    mov esi, 10
    mov ah, 7
    mov [myTable+esi*4], ah
    mov cl, [myTable+esi*4]
    add cl, '0'   
 
    mov [stdoutBuff], cl
    mov eax, 4
    mov ebx, 1
    lea ecx, [stdoutBuff]
    mov edx, 1
    int 0x80 

    mov eax, 1
    int 0x80


section .bss
myTable  resb mySize*mySize

section .data
stdoutBuff     db 0

Kod:
rgawron@foo:/opt/asmy$ nasm -O3 -f elf sth.asm && ld -o hello sth.o && ./hello 
7rgawron@foo:/opt/asmy$

Dlaczego poniższy kod, w którym zapisuje dane do komórki, która nie istnieje też się kompiluje i też działa? W poniższym przykładzie myTable jest za mała przecież, żeby się do niej tak odwołać.

Kod:
section .text
global _start

%define mySize 10

_start:
    mov esi, 10
    mov ah, 7
    mov [myTable+esi*4], ah
    mov cl, [myTable+esi*4]
    add cl, '0'   
 
    mov [stdoutBuff], cl
    mov eax, 4
    mov ebx, 1
    lea ecx, [stdoutBuff]
    mov edx, 1
    int 0x80 

    mov eax, 1
    int 0x80


section .bss
myTable  resb 1

section .data
stdoutBuff     db 0

Kod:
rgawron@foo:/opt/asmy$ nasm -O3 -f elf sth.asm && ld -o hello sth.o && ./hello 
7rgawron@foo:/opt/asmy$


Czy ten kod, który zaprezentowałem niżej jest poprawny, czy też jest błędny a działa tylko przez przypadek? Jeżeli jest błędny to jakie narzędzia, z jakimi flagami mogą pomóc w analizie takich sytuacji? (valgrind pisze, iż jest OK, szukałem w manualu NASMa jakiejś opcji dającej więcej info o ostrzeżeniach ale też nie znalazłem)

pozdrawiam serdecznie
 

grzonu

Były Moderator
Dołączył
Grudzień 26, 2006
Posty
1390
tablica ma rozmiar 1 jak widze a przeciez rejestr ah tez ma 1 bajt(chyba ze sie myle).
 

RobertG

Użytkownik
Dołączył
Styczeń 3, 2007
Posty
391
Tak ale do tej tablicy, nawet o rozmiarze 1 można zapisać wiele zmiennych i to się nie wywala - nie wiem dlaczego. IMHO Twoje rozwiązanie nie tłumaczy, dlaczego poniższy kod działa:

Kod:
section .text
global _start

%define stdout  1
%define sthSize 9

_start:
    call setsthTable
    call printsthTable
    mov eax, 1
    int 0x80

setsthCell:
 ; count index
    push esi
    xor esi, esi
    mov si, ax
    imul si, sthSize
    add si, bx
 ; count value
    push ebx
    push eax
    add al, bl
    mov bl, 0x9
    div bl
    inc ah; need values couned from 1
    mov [myTable+esi*4], ah
    pop eax
    pop ebx
    pop esi
    ret

getsthCell:
    xor esi, esi
    mov si, ax
    imul si, sthSize
    add si, bx
    mov cl, [myTable+esi*4]
    ret

setsthTable:
 ; ax - horizontal value, bx - vertical value
    mov ax, sthSize
L0:
    mov bx, sthSize
L1:
    call setsthCell
 ; update horizontal index
    dec bx
    test bx, bx
    jg L1
 ; update vertical index
    dec ax
    test ax, ax
    jg L0
    ret

printsthTable:
 ; ax - horisontal, bx - vertical
    mov ax, sthSize
L2:
    mov bx, sthSize
L3:
    call getsthCell; returns in al cells value
    add cl, 0x30; add ASCII value of 0, to make this printable
    call printSignOnStandardOutput
 ; print 2x space sign between numbers
    mov cl, 0x20
    call printSignOnStandardOutput
    call printSignOnStandardOutput
 ; update horizontal index
    dec bx
    test bx, bx
    jg L3
 ; insert new line at the end of the row
    mov cl, 0xa
    call printSignOnStandardOutput
 ; update vertical index
    dec ax
    test ax, ax
    jg L2
    ret

; sign is passed in cl
printSignOnStandardOutput:
    pusha
    mov [stdoutBuff], cl
    mov eax, 4
    mov ebx, stdout
    lea ecx, [stdoutBuff]
    mov edx, 1
    int 0x80 
    popa
    ret

section .bss
myTable  resb 1

section .data
stdoutBuff     db 0

Tutaj wciąż tablica ma rozmiar jeden, a udało mi się do niej wpakować 81 wartości :/

Kod:
rgawron@foo:/opt/asmy$ cat Makefile && make && ./hello 
all:
        nasm -O3 -f elf hello.asm && ld -o hello hello.o
nasm -O3 -f elf hello.asm && ld -o hello hello.o
1  9  8  7  6  5  4  3  2  
9  8  7  6  5  4  3  2  1  
8  7  6  5  4  3  2  1  9  
7  6  5  4  3  2  1  9  8  
6  5  4  3  2  1  9  8  7  
5  4  3  2  1  9  8  7  6  
4  3  2  1  9  8  7  6  5  
3  2  1  9  8  7  6  5  4  
2  1  9  8  7  6  5  4  3
 

grzonu

Były Moderator
Dołączył
Grudzień 26, 2006
Posty
1390
no tak, przeciez poprostu nadpisujesz poprostu stos... wkoncu nadejdzie moment ze nadpiszesz cos czego nie powinienes a wtedy bedzie seg fault
smile.gif

przesledz dzialanie w debuggerze to zobaczysz czemu sie nie crashuje odrazu
 

RobertG

Użytkownik
Dołączył
Styczeń 3, 2007
Posty
391
OK, a czy znasz/znacie narzędzia które wskazały by w takim miejscu błąd, coś jak valgrind przy niezwalnianiu zalokowanej pamięci, czy jakikolwiek inny sposób, by się wyszukać takie sytuacje w kodzie (np. flagi kompilatora, linkera etc?). Czy można jakoś binarkę odpalić, by się wywaliła, mając takie błędy?
 

grzonu

Były Moderator
Dołączył
Grudzień 26, 2006
Posty
1390
hmmmm nie przychodzi mi nic do glowy.
Nigdy nie uzywalem do tego innych narzedzi. Zwykle poprostu obserwuje program w debuggerze ale to wykryje jesli jest error.
A jesli nie ma to to latwo przeoczyc w malym programie bo nie powoduje zwykle zmiany dzialania. Ale w czyms wiekszym moze nadpisac cos czego bedziemy uzywac pozniej i sie robi problem i to latwo zauwazyc w zlym dzialaniu programu a wtedy debugger:
-szukamy miejsca gdzie jest error -> patrzymy co nam zmienia pamiec
 

shoorick

Użytkownik
Dołączył
Lipiec 17, 2008
Posty
66
nie znam jak w Linuksie, ale we Windie pamiec wydaje sie blokami (4kb?) i niema faultu przy akcesi do cialego bloku. Sprobuj pisac daleko od myTable zeby otrymac blad abo zrob swoj kontrol rozmiaru jezeli trzeba.

pozdraw!
 

grzonu

Były Moderator
Dołączył
Grudzień 26, 2006
Posty
1390
ale tu chodzi o wykrycie sytuacji kiedy jedna zmienna nadpisuje druga
 

shoorick

Użytkownik
Dołączył
Lipiec 17, 2008
Posty
66
wtedy najlepszy jest wlasny kontrol jesly rozmiar tablicy jest dinamiczny albo w kode wykorystaty symboly jak mySize zamiast cyfrowych parametrow.
 

grzonu

Były Moderator
Dołączył
Grudzień 26, 2006
Posty
1390
wlasnie chodzi o to ze wiadomo ze własna kontrola jest potrzebna, ale czy mozna to jakos programowo sprawdzic, tak zeby np. kompilator/linker nam o tym powiedzial
 

shoorick

Użytkownik
Dołączył
Lipiec 17, 2008
Posty
66
nie dumam to jest mozlywo: asembler kontroluje tylko czy jest adresa "myTable", ale nie bedzie obliczac kompletnoj adresy bo to jest skomplikowane abo nawet niemozlywo, ale biez komplietnej adresy niemozlywo wiedec czy jest zwrocenie sie do blednej komorky. tym bardzej to jest niemozlywo dla linkera.
 
Do góry Bottom