• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Kod z asembler na C, problem

Object Storage Arubacloud
0 głosów
266 wizyt
pytanie zadane 19 maja 2020 w C i C++ przez chillin Nowicjusz (200 p.)
Witam,

Muszę zapisać poniższy kod z assemblera na język C. Czy mogę prosić o jakieś wskazówki?
Kompletnie nie wiem jak zacząć.
Z góry dziękuję za pomoc.

MOV AX,01   
CMP AX,00   
JE L7            
MOV BX,01
L7:MOV BX,2

2 odpowiedzi

+2 głosów
odpowiedź 19 maja 2020 przez VirtualMember Pasjonat (15,790 p.)
Instrukcja MOV DST, SRC kopiuje wartość SRC do DST. Instrukcja CMP FST, SND porównuje dwie wartości. JE to skok warunkowy: jump if equal (czyli jeśli flaga równości jest ustawiana a ta jest ustawiana w tym przypadku przez CMP). L7: to tylko label gdzie ma zacząć się kod po przeskoczeniu.
komentarz 20 maja 2020 przez chillin Nowicjusz (200 p.)
Dziękuje z pomoc :)
0 głosów
odpowiedź 19 maja 2020 przez Chess Szeryf (76,710 p.)
edycja 25 maja 2020 przez Chess
var ax = 1

if(ax == 0) then
  var bx = 2
else
  var bx = 1
end if

Napisałem jako pseudokod.

Jeśli, gdzieś się pomyliłem, to proszę mnie poprawić.

Edit... A jednak się pomyliłem, komentarze poniżej, dziękuję @Piotr Batko za review. Kod, który jest powyżej odzwierciedla ten poniżej.


[bits 32]

global _main
extern _printf

section .data

fmt1: db "bx <-- %hu", 0

section .text


_main:

mov ax, 1 ; was 1

cmp ax, 0
je L7

mov bx, 1
jmp L8

L7:

mov bx, 2

L8:


push bx
push fmt1
call _printf
add esp, 6

ret

Natomiast odpowiedź na kod autora, jest taka <tutaj_link_do_komentarza>.

Intel manual - 176 strona teraz na tym pdf, a jest to rozdział 7.3.2.4.

Opis CMP dokładny masz na 728. stronie. Vol. 2A.

Pseudokod z ich manuala, jest taki.

temp <-- SRC1 - SignExtend(SRC2);
ModifyStatusFlags; (* Modify status flags in the same manner as the SUB instruction*)

Co to jest temp, SRC1, etc. doczytasz w manualu Intela i innych dokumentach traktującym o zagadnieniach.

komentarz 20 maja 2020 przez chillin Nowicjusz (200 p.)
Dziękuje z pomoc :)
komentarz 20 maja 2020 przez Piotr Batko Stary wyjadacz (13,190 p.)

@Chess, Mógłbyś mi wytłumaczyć dlaczego gdy AX będzie różne od 0, po instrukcji: MOV BX,01 miałaby się nie wykonać kolejna instrukcja L7:MOV BX,2?

Według mnie powinno się to zachować tak:

ax = 1

if (ax != 0) then
  bx = 1
end if

bx = 2
1
komentarz 20 maja 2020 przez Chess Szeryf (76,710 p.)
edycja 20 maja 2020 przez Chess

Trochę nie rozumiem, bo chyba pytasz o dwie różne rzeczy. Napisałeś kod, który jest taki w assembly x86 (napiszę go poniżej).


[bits 32]


global _main
extern _printf
extern _exit

section .data


fmt1: db "%u", 0 ; format to printf have 8 bits type of "variable"

section .text


_main:

mov eax, 1

cmp eax, 0
jne L7

; do something and exit from program
; ret?

L7:

mov ebx, 1

mov ebx, 2

push ebx
push fmt1
call _printf
pop eax
pop eax

; or add esp, 8

ret



section .bss


; compilation ; nasm -fwin32 pseudocode1.asm && gcc pseudocode1.obj -o pc1.exe && pc1.exe ; => 2
; echo %errorlevel% ; => 2 (should support a exit from program correctly rather, so belongs fix it)
; probably this ; https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499- ??

W Twoim kodzie jest bezużyteczny if, bo, czy ax jest różne, czy równe 0, to na końcu wartość bx i tak zawsze będzie wynosić 2 (bx = 2).

Linia "jne L7", oznacza "jump if not equal".  Więc, jeśli "eax != 0", to następnie program ma iść do linii, gdzie jest napisane "L7:" i później napotka "enter - pustą linię" i dalej "mov ebx, 1". Koniec końców instrukcja warunkowa coś sprawdza, ale nic z tym konkretnego nie robi, nawet nie wykonuje kopii "zmiennej", tylko nadpisuje wartość powodując tylko, że jeśli kompilator wykryje, że if jest fizycznie w kodzie, ale jest niepotrzebny i np. zwiększa rozmiar pliku wynikowego, to po prostu (o ile się nie mylę) "wycina" z kodu ten fragment, ale proszę nie wierzyć mi na słowo, tylko poczytać jak działa kompilator.

A to, o co pytasz. Kolejna instrukcja się nie wykona, ponieważ (chyba) kompilator wejdzie w albo gałąź if then albo w if else, ale wtedy kod mógłby wyglądać np. tak.

; ...
section .text


_main:

mov eax, 0

cmp eax, 0
jne L7

mov ebx, 2
;push ebx
;push fmt1
;call _printf
;add esp, 8
ret

L7:

mov ebx, 1

push ebx
push fmt1
call _printf
pop eax
pop eax

; or add esp, 8

ret



section .bss
; ...

Po uruchomieniu programu, będzie widnieć "nic", dlatego, że nie jest nic wyświetlone na wyjściu (output). Żeby zobaczyć, że tam będzie 2 dla gałęzi if else, to odkomentuj kod od "push ebx" do "add esp, 8".

Po zmianie linii początkowej "mov eax, 0" na np. "mov eax, 5", na ekranie powinna ukazać się cyfra 1, bo wykona się kod "mov ebx, 1".

komentarz 21 maja 2020 przez Piotr Batko Stary wyjadacz (13,190 p.)

Już rozumiem dlaczego inaczej interpretujemy ten kod. Ty zakładasz, że przed L7 może być jeszcze wiele instrukcji i na pewno będzie zakończenie programu. Ja założyłem, że kod jest taki jak w poleceniu, (wklejam poniżej dla wygody). Dobrze myślę? :)

    MOV AX, 01
    CMP AX, 00
    JE  L7            
    MOV BX, 01
L7: MOV BX, 02

Odnośnie tego co piszesz o optymalizacjach: w tym kodzie który wkleiłeś wcześniej (wklejam poniżej) też jest "bezużyteczny if" w linii 3., bo przecież ax jest już w czasie kompilacji równe 1, więc bx też zawsze będzie równe 1 i kompilator będzie to optymalizował.

var ax = 1
 
if(ax == 0) then
  var bx = 2
else
  var bx = 1
end if

Ja myślę, że kod przedstawiony przez autora tematu jest zadaniem domowym z jakichś pierwszych zajęć z przedmiotu i na pewno nie chodzi o to, żeby przewidywać jak się zachowa optymalizator. Trzeba zamienić dane instrukcje (czy one mają sens czy nie) na kod w C.

Fajnie tłumaczysz wszystko ze szczegółami. Dzięki za odpowiedź :)

komentarz 23 maja 2020 przez Chess Szeryf (76,710 p.)
edycja 23 maja 2020 przez Chess

Odnośnie pierwszego. Zredaguj i zadaj pytanie jeszcze raz, ponieważ nie chcę się domyślać.

Drugie. Raczej nie, tam może być input, jakiś putchar i wtedy ax może wynosić 0, więc wykona się blok kodu dotyczący true.

Ja nie piszę o optymalizacji jako takiej, tylko o tym, że Twój snippet code nie ma według mnie realnego zastosowania. Nie wiem, przecież to oczywiste, że ustawienie bx na xxx (1), a później na yyy (2) jest "daniem/dodaniem dodatkowej pracy dla kompilatora", a nic z tym ciekawego się nie dzieje, wspomniana wcześniej kopia zmiennej, czy cokolwiek, co "przydałoby się" w programie.

Trzeba zamienić dane instrukcje (czy one mają sens czy nie) na kod w C.

To przecież napisałem kod, który jest możliwą odpowiedzią na główny core wątku.

Może jeszcze raz dot. drugiego pytania. Mój kod jest taki. Gdy ręcznie się zmieni w kodzie wartość zmiennej ax, to zależnie od tej wartości, zmiennej bx jest przypisane albo 2 albo 1. I jak już pisałem, putchar mógłby być zastosowany.

W kodzie, który zaprezentowałeś jest zawsze bx = 2, więc jak dla mnie jest kodem widmo.

komentarz 23 maja 2020 przez Piotr Batko Stary wyjadacz (13,190 p.)
W pierwszym pytaniu prosiłem Cię o potwierdzenie, czy dobrze zrozumiałem Twoje założenie o ukrytym kodzie przed L7 i wyjaśniłem dlaczego tak interpretuję zamieszczony listing.

Co do drugiego: W listingu jest przypisanie jedynki. Mam wrażenie, że nie możemy się dogadać, bo ja mówię o kodzie przedstawionym przez autora tematu, a Ty mówisz o kodzie, który na bieżąco wymyślasz. Jakby była instrukcja ret przed L7, i putchar zamiast 1 to masz rację, no ale ich nie ma.
komentarz 24 maja 2020 przez Chess Szeryf (76,710 p.)
1. "Nie wiem, co autor miał na myśli." Jaki ukryty kod? Napisz przykład, mógbym opisać. I tam nie musi być zakończenia programu, wystarczy wyrzucić ret.

2. Tak, jest przypisanie wartości jeden. Tak, także mówię o kodzie autora, tylko podałem dodatkowe przykłady. Jeśli w kodzie jest "L7" i" L7:", to staraj się sprecyzować o którym piszesz. Dobra, ale  Twój kod w mojej opinii jest (bardziej) no-use/useless już do tej pory bez "gdybania", co dopisać później. I nie do końca wiem, co ten kod wnosi do przykładu.

Ogółem, możliwe iż nie wiesz jak działają jumpsy w assembly, ale nie mam co do tego pewności, więc nie będę polemizował.
komentarz 25 maja 2020 przez Piotr Batko Stary wyjadacz (13,190 p.)

Twój pseudokod:

var ax = 1
 
if(ax == 0) then
  var bx = 2
else
  var bx = 1
end if

Odpowiada temu kodzikowi:

    MOV AX, 01
    CMP AX, 00
    JE  L7            
    MOV BX, 01
    RET        ; To RET sobie dodałeś, bo inaczej
               ; program jest "useless"
L7: MOV BX, 02

A pytanie było o inny kod, taki:

    MOV AX, 01
    CMP AX, 00
    JE  L7            
    MOV BX, 01
               ; Tu nie ma RETa
L7: MOV BX, 02

Nie jestem specjalistą od Asembly, ale z tego co rozumiem, to ten kod zachowa się tak, jak napisałem wyżej:

ax = 1
 
if (ax != 0) then
  bx = 1
end if
 
bx = 2

Zgadzam się, że ten kod jest bezużyteczny, ale to ćwiczenie na zajęcia w szkole. Tam często się pisze bezużyteczne programy, żeby się na nich czegoś nauczyć.

1
komentarz 25 maja 2020 przez Chess Szeryf (76,710 p.)
edycja 25 maja 2020 przez Chess

Dziękuję bardzo za zwrócenie uwagi i feedback, aby nie szerzyć herezji ewentualnej dotyczącego kodu autora, bo rzeczywiście dodałem do niego "ret".

Poniżej kod według kodu asm autora.

var ax = 1

if(ax == 0) then
  var bx = 2
else
  var bx = 1
  var bx = 2
end if

exit;

Dzięki jeszcze raz, zaraz poprawię odpowiedź, bo jakoś niedostrzegłem tego, ale dobrze, że napisałem wtrącenie.

Jeśli, gdzieś się pomyliłem, to proszę mnie poprawić.

Twój kod będzie według mnie taki (jedna z możliwości).


[bits 32]

global _main
extern _printf

section .data


fmt1: db "%hu", 0

section .text

_main:

mov ax, 1 ; Change later for test to value 0.

cmp ax, 0
jne L7
je L8

L7:
  mov bx, 1
  L8:
    mov bx, 2
    
push bx         ; 2 bytes (16 bits)
push fmt1       ; 4 bytes (32 bits) - as default?
call _printf
add esp, 6      ; 6 bytes all to cleanest
    
; Always should be value 2 on the output e.g. standard output.

ret


section .bss ; You mustn't write it, if You don't need.

Objaśnię może "cmp ax, 0 \ jne L7 \ je L8" - "\" jako znak nowej linii.

Trzy instrukcje jedna po drugiej znaczą. Jeśli ax jest różne od 0, to goto (idź do) labela (etykiety) L7:, a gdy ax jest równe 0, to skocz do L8:.

Możesz jak chcesz skorzystać z serwisu https://godbolt.org/.

Podobne pytania

0 głosów
1 odpowiedź 494 wizyt
pytanie zadane 12 maja 2020 w Assembler przez evela Nowicjusz (120 p.)
+1 głos
2 odpowiedzi 609 wizyt
pytanie zadane 6 lutego 2018 w Assembler przez Paweł Piech Użytkownik (720 p.)
0 głosów
0 odpowiedzi 35 wizyt
pytanie zadane 1 grudnia 2023 w Assembler przez hutsalo1998 Użytkownik (520 p.)

92,555 zapytań

141,403 odpowiedzi

319,557 komentarzy

61,940 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...