Assembly-kieli ja x86-tason järjestelmäohjelmointi · Oppitunti

Ehdolliset hypyt ja silmukat

Toteuttakaa päätöksenteko ja toistuvat tehtävät vertailukäskyillä (CMP, TEST) ja ehdollisilla hyppykäskyillä (JMP, JE, JNE, JL, JG jne.).

Oppitunti 3/411 vaihetta

Ehdolliset hypyt ja silmukat on ilmainen Assembly-kieli ja x86-tason järjestelmäohjelmointi-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Assembly-kieli ja x86-tason järjestelmäohjelmointi-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Assembly-kieli ja x86-tason järjestelmäohjelmointi-kurssilla on yhteensä 4 oppituntia.

Ohjelman suorituksen ohjaaminen

Ohjelmat suoritetaan harvoin alusta loppuun suoraviivaisesti. Meidän on tehtävä päätöksiä ja toistettava toimintoja. Tätä kutsutaan suorituksen ohjaukseksi.

Assembly-kielessä on erityisiä käskyjä, joilla voidaan muuttaa käskyjen suoritusjärjestystä. Näin ohjelmat voivat toimia dynaamisesti ja reagoida erilaisiin ehtoihin.

Ajatelkaa sitä kuin tarinaa, jossa valitsette itse seuraavan tapahtumapolun: päätätte, mitä reittiä kuljette seuraavaksi!

Hyppy suoritetaan aina

Yksinkertaisin tapa muuttaa ohjelman suorituksen kulkua on käyttää ehdotonta hyppyä JMP-käskyllä. Se siirtää ohjauksen aina määritettyyn tunnisteeseen.

Tämä vastaa ylemmän tason kielten "goto"-lausetta. Ohjelma alkaa välittömästi suorittaa kohdetunnisteesta alkavia käskyjä.

section .data
    msg1 db "Hello!", 0xA
    len1 equ $ - msg1
    msg2 db "Skipped!", 0xA
    len2 equ $ - msg2
    msg3 db "End.", 0xA
    len3 equ $ - msg3

section .text
    global _start

_start:
    mov rax, 1           ; syscall write
    mov rdi, 1           ; stdout
    mov rsi, msg1
    mov rdx, len1
    syscall              ; Print "Hello!"

    jmp skip_message     ; Unconditional jump

    mov rax, 1
    mov rdi, 1
    mov rsi, msg2
    mov rdx, len2
    syscall              ; This part is skipped!

skip_message:
    mov rax, 1
    mov rdi, 1
    mov rsi, msg3
    mov rdx, len3
    syscall              ; Print "End."

    mov rax, 60          ; syscall exit
    mov rdi, 0
    syscall

Vertailujen tekeminen (CMP)

Ennen päätösten tekemistä meidän on verrattava arvoja. CMP-käsky tekee tämän puolestamme.

CMP destination, source toimii kuten SUB destination, source, mutta se hylkää tuloksen. Sen sijaan se päivittää vain suorittimen liput vertailun perusteella.

Tämä on ratkaisevan tärkeää ehdollisille hypyille!

; Compare AX with BX
cmp ax, bx

; Compare value in memory with 10
cmp [my_var], 10

; Compare AL with 0
cmp al, 0

Suorittimen lippurekisteri

CMP-käskyn (tai useimpien aritmeettisten ja loogisten operaatioiden) jälkeen lippurekisterin erityiset bitit päivitetään. Nämä bitit kertovat operaation tuloksesta.

  • ZF (Zero Flag): Asetetaan, jos tulos oli nolla tai operandit olivat yhtä suuret.
  • SF (Sign Flag): Asetetaan, jos tulos oli negatiivinen.
  • CF (Carry Flag): Asetetaan, jos tapahtui etumerkitön ylivuoto.
  • OF (Overflow Flag): Asetetaan, jos tapahtui etumerkillinen ylivuoto.

Ehdolliset hypyt tarkistavat nämä liput!

Hyppy yhtäsuuruuden perusteella (JE, JNE)

Kun CMP on asettanut liput, voimme käyttää ehdollisia hyppykäskyjä. Kaksi yleistä käskyä ovat JE (Jump if Equal) ja JNE (Jump if Not Equal).

  • JE label: Hyppää, jos nollalippu (ZF) on asetettu eli operandit olivat yhtä suuret.
  • JNE label: Hyppää, jos nollalippu (ZF) ei ole asetettu eli operandit eivät olleet yhtä suuret.

Katsotaan esimerkkiä.

section .data
    eq_msg db "Numbers are equal!", 0xA
    eq_len equ $ - eq_msg
    ne_msg db "Numbers are not equal!", 0xA
    ne_len equ $ - ne_msg

section .text
    global _start

_start:
    mov rax, 10
    mov rbx, 10          ; Try changing this to 5

    cmp rax, rbx         ; Compare RAX and RBX

    je  are_equal        ; If equal, jump to are_equal

    ; Else (not equal)
    mov rax, 1
    mov rdi, 1
    mov rsi, ne_msg
    mov rdx, ne_len
    syscall
    jmp end_program

are_equal:
    mov rax, 1
    mov rdi, 1
    mov rsi, eq_msg
    mov rdx, eq_len
    syscall

end_program:
    mov rax, 60
    mov rdi, 0
    syscall

Suurempi tai pienempi (etumerkilliset luvut)

Etumerkillisille luvuille käytämme erilaisia ehdollisia hyppyjä tarkistaessamme suurempi kuin- tai pienempi kuin -suhteita.

  • JG label: Hyppää, jos suurempi (ZF=0 ja SF=OF)
  • JGE label: Hyppää, jos suurempi tai yhtä suuri (SF=OF)
  • JL label: Hyppää, jos pienempi (SF!=OF)
  • JLE label: Hyppää, jos pienempi tai yhtä suuri (ZF=1 tai SF!=OF)

Nämä perustuvat Sign Flag (SF)-, Overflow Flag (OF)- ja Zero Flag (ZF) -lippujen yhdistelmiin.

section .data
    gt_msg db "RAX is greater!", 0xA
    gt_len equ $ - gt_msg
    lt_msg db "RAX is less!", 0xA
    lt_len equ $ - lt_msg
    eq_msg db "RAX is equal!", 0xA
    eq_len equ $ - eq_msg

section .text
    global _start

_start:
    mov rax, 5
    mov rbx, 10          ; Compare 5 with 10

    cmp rax, rbx

    jg  is_greater       ; If RAX > RBX
    jl  is_less          ; If RAX < RBX

    ; Else, they must be equal
    mov rsi, eq_msg
    mov rdx, eq_len
    jmp print_msg

is_greater:
    mov rsi, gt_msg
    mov rdx, gt_len
    jmp print_msg

is_less:
    mov rsi, lt_msg
    mov rdx, lt_len
    jmp print_msg

print_msg:
    mov rax, 1
    mov rdi, 1
    syscall

    mov rax, 60
    mov rdi, 0
    syscall

Etumerkittömät vertailut (JA, JB)

Etumerkittömiä lukuja käsiteltäessä lippuja tulkitaan eri tavalla. Carry Flag (CF) on tällöin keskeinen.

  • JA label: Hyppää, jos suurempi (etumerkitön vertailu) (CF=0 ja ZF=0)
  • JAE label: Hyppää, jos suurempi tai yhtä suuri (etumerkitön vertailu) (CF=0)
  • JB label: Hyppää, jos pienempi (etumerkitön vertailu) (CF=1)
  • JBE label: Hyppää, jos pienempi tai yhtä suuri (etumerkitön vertailu) (CF=1 tai ZF=1)

Huomioikaa aina, vertailetteko etumerkillisiä vai etumerkittömiä arvoja!

IF-ELSE-lohkon rakentaminen

Voimme yhdistää CMP-käskyn ja ehdolliset hypyt if-else-logiikan luomiseksi aivan kuten ylemmän tason kielissä.

Yleinen rakenne on seuraava: vertaile, hyppää ehdon ollessa EPÄTOSI "else"-lohkoon, suorita "if"-lohko ja hyppää sitten "else"-lohkon ohi.

section .data
    if_msg db "Condition is TRUE!", 0xA
    if_len equ $ - if_msg
    else_msg db "Condition is FALSE!", 0xA
    else_len equ $ - else_msg

section .text
    global _start

_start:
    mov rax, 20
    mov rbx, 10

    cmp rax, rbx         ; Is RAX > RBX?
    jle else_block       ; If not (less or equal), jump to else

    ; IF block (RAX > RBX)
    mov rsi, if_msg
    mov rdx, if_len
    jmp print_and_exit

else_block:
    ; ELSE block (RAX <= RBX)
    mov rsi, else_msg
    mov rdx, else_len

print_and_exit:
    mov rax, 1
    mov rdi, 1
    syscall

    mov rax, 60
    mov rdi, 0
    syscall

Silmukoiden luominen hypyillä

Silmukat ovat keskeisiä koodin toistamisessa. Assemblyssa ne luodaan yhdistämällä tunniste, vertailu ja ehdollinen hyppy.

Yleiseen rakenteeseen kuuluu laskurin alustaminen, silmukan tunnisteen määrittäminen, operaatioiden suorittaminen, laskurin pienentäminen tai kasvattaminen, vertailu ja hyppääminen takaisin tunnisteeseen, jos ehto täyttyy.

section .data
    msg db "Looping... ", 0xA
    len equ $ - msg

section .text
    global _start

_start:
    mov rcx, 3           ; Initialize loop counter

loop_start:
    cmp rcx, 0           ; Check if counter is 0
    je  loop_end         ; If it is, exit loop

    ; Print message
    mov rax, 1
    mov rdi, 1
    mov rsi, msg
    mov rdx, len
    syscall

    dec rcx              ; Decrement counter
    jmp loop_start       ; Jump back to start of loop

loop_end:
    mov rax, 60
    mov rdi, 0
    syscall

Hyppyehdon tarkistus

Tarkastelkaa seuraavaa assembly-koodikatkelmaa. Mitä tulostetaan, jos RAX sisältää arvon 5 ja RBX sisältää arvon 10?

section .data
    msg_a db "Result A", 0xA
    len_a equ $ - msg_a
    msg_b db "Result B", 0xA
    len_b equ $ - msg_b

section .text
    global _start

_start:
    ; Assume RAX = 5, RBX = 10
    cmp rax, rbx
    jg  print_a
    jmp print_b

print_a:
    mov rax, 1
    mov rdi, 1
    mov rsi, msg_a
    mov rdx, len_a
    syscall
    jmp end_program

print_b:
    mov rax, 1
    mov rdi, 1
    mov rsi, msg_b
    mov rdx, len_b
    syscall

end_program:
    mov rax, 60
    mov rdi, 0
    syscall

Kertaus: hypyt ja silmukat

Hienoa työtä! Olette oppineet ohjaamaan ohjelman suorituksen kulkua assemblyssa!

  • JMP on tarkoitettu ehdottomiin hyppyihin.
  • CMP vertailee arvoja ja päivittää suorittimen lippurekisterin.
  • Ehdolliset hypyt, kuten JE, JNE, JG, JL, JA ja JB, tarkistavat nämä liput päättääkseen, hypätäänkö.
  • Yhdistämällä nämä voitte luoda tehokkaita if-else-lauseita ja silmukoita.

Seuraavaksi perehdymme proseduureihin ja pinon hallintaan, jotta voitte jäsentää koodianne entistä paremmin!

Aloita maksutta

Opi Assembly tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
12
Oppitunnit
48

Usein kysytyt kysymykset

Onko oppitunti ”Ehdolliset hypyt ja silmukat” ilmainen?

Kyllä – oppitunnin ”Ehdolliset hypyt ja silmukat” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Assembly-kieli ja x86-tason järjestelmäohjelmointi-kurssin, päivitä CoddyKit PROhon. Assembly-kieli ja x86-tason järjestelmäohjelmointi-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Ehdolliset hypyt ja silmukat”?

Toteuttakaa päätöksenteko ja toistuvat tehtävät vertailukäskyillä (CMP, TEST) ja ehdollisilla hyppykäskyillä (JMP, JE, JNE, JL, JG jne.). Harjoittelet Assembly-kieli ja x86-tason järjestelmäohjelmointi-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Assembly-kieli ja x86-tason järjestelmäohjelmointi-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Assembly-kieli ja x86-tason järjestelmäohjelmointi-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”Ehdolliset hypyt ja silmukat”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Assembly-kieli ja x86-tason järjestelmäohjelmointi-oppitunnilla?

Kyllä. Jokainen Assembly-kieli ja x86-tason järjestelmäohjelmointi-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Datan siirtokäskyt (MOV, PUSH, POP)
  2. Aritmeettiset ja loogiset operaatiot
  3. Ehdolliset hypyt ja silmukat
  4. Bittikohtaiset ja siirtokäskyt
← Takaisin: Assembly-kieli ja x86-tason järjestelmäohjelmointi