Practice7 Explanation - GawinGowin/libasm GitHub Wiki
-
å ç¢ãªããã°ã©ãã³ã°ã®ç¿åŸ
- ãšã©ãŒç¶æ³ã®é©åãªæ€åº
- ãšã©ãŒæ å ±ã®æ£ç¢ºãªå ±å
- äºæããªãå ¥åãžã®å¯Ÿå¿
-
ã·ã¹ãã ããã°ã©ãã³ã°ã®çè§£
- errnoæ©æ§ã®å®è£
- ã©ã€ãã©ãªé¢æ°ã®æšæºçãªãšã©ãŒåŠç
- Cæšæºã©ã€ãã©ãªãšã®äºææ§
-
æ¡ä»¶åå²ãšã©ãã«ã®å®è·µ
-
.error:
ã©ãã«ã®æŽ»çš - æ¡ä»¶ãžã£ã³ãåœä»€ã®äœ¿ãåã
- ããã°ã©ã ãããŒã®å¶åŸ¡
-
; practice7.s - å®å
šãªé€ç®é¢æ°ã®å®è£
section .text
global safe_divide
extern __errno_location
safe_divide:
push rbp
mov rbp, rsp
cmp rsi, 0 ; check if divisor is zero
je .error ; if zero, jump to error handler
mov rax, rdi ; dividend to rax
cqo ; sign extend rax to rdx:rax
idiv rsi ; signed division: rax = rax / rsi
leave
ret
.error:
push rax ; preserve registers
call __errno_location wrt ..plt
mov qword [rax], 22 ; set errno to EINVAL (22)
pop rax
mov rax, -1 ; return error value
leave
ret
long safe_divide(long dividend, long divisor);
æ©èœ:
- æŽæ°é€ç®ãå®å šã«å®è¡
- ãŒãé€ç®ãšã©ãŒãæ€åºã»å ±å
- æ»ãå€: é€ç®çµæ (ãšã©ãŒæã¯ -1)
- ãšã©ãŒæ: errno ã« EINVAL (22) ãèšå®
æ£åžžãªé€ç®: 20 / 4 = 5
ãšã©ãŒæ¡ä»¶: 10 / 0 = ??? (undefined behavior)
â ãšã©ãŒæ€åºã«ããå®å
šãªå®è¡ãä¿èšŒ
push rbp
mov rbp, rsp
ã¹ã¿ãã¯ãã¬ãŒã èšå®ã®è©³çް:
颿°ããããŒã° (Function Prologue):
- æšæºçãªé¢æ°éå§åŠç
- åŒã³åºãå ã®ç¶æ ãä¿å
- çŸåšã®é¢æ°çšã®ã¹ã¿ãã¯é åã確ä¿
push rbpåœä»€ã®åœ¹å²:
push rbp ; åŒã³åºãå
ã®ããŒã¹ãã€ã³ã¿ãä¿å
- åŒã³åºãå
颿°ã®
rbp
ïŒããŒã¹ãã€ã³ã¿ïŒãã¹ã¿ãã¯ã«éé¿ - ã¹ã¿ãã¯ãã€ã³ã¿
rsp
ã8ãã€ãæžå° - 颿°çµäºæã«åŸ©å ããããã®æºå
mov rbp, rspåœä»€ã®åœ¹å²:
mov rbp, rsp ; çŸåšã®ã¹ã¿ãã¯ãã€ã³ã¿ãæ°ããããŒã¹ãã€ã³ã¿ã«
- çŸåšã®ã¹ã¿ãã¯ãã€ã³ã¿
rsp
ã®å€ãrbp
ã«ã³ã㌠- æ°ããã¹ã¿ãã¯ãã¬ãŒã ã®ããŒã¹ã¢ãã¬ã¹ãèšå®
- ããã«ããçŸåšã®é¢æ°å°çšã®åç §ç¹ã確ç«
ã¹ã¿ãã¯ãã¬ãŒã ã®æ§é :
é«äœã¢ãã¬ã¹
âââââââââââââââ
â åŒã³åºãå
â
â ã®ããŒã¿ â
ââââââââââââââ†â å
ã®rbp
â ä¿åãããrbpâ â push rbpã§ä¿å
âââââââââââââââ€ â æ°ããrbp (çŸåšã®rsp)
â ããŒã«ã«å€æ°â
â (ããã°) â
ââââââââââââââ†â çŸåšã®rsp
â æé·æ¹å â
â â â
äœäœã¢ãã¬ã¹
leaveåœä»€ãšã®å¯Ÿå¿é¢ä¿:
leave ; 颿°ãšãããŒã°
leaveåœä»€ã®åäœè©³çް:
; leave ã¯ä»¥äžã®2ã€ã®åœä»€ãšç䟡:
mov rsp, rbp ; ã¹ã¿ãã¯ãã€ã³ã¿ãããŒã¹ãã€ã³ã¿ã«æ»ã
pop rbp ; ä¿åãããŠããããŒã¹ãã€ã³ã¿ã埩å
ã¹ã¿ãã¯ãã¬ãŒã 埩å ã®æµã:
-
mov rsp, rbp
: ã¹ã¿ãã¯ãã€ã³ã¿ã颿°éå§æã®äœçœ®ã«æ»ã -
pop rbp
: ããã·ã¥ãããåŒã³åºãå ã®ããŒã¹ãã€ã³ã¿ã埩å - ã¹ã¿ãã¯ã颿°åŒã³åºãåã®ç¶æ ã«å®å šåŸ©å
ããããŒã°ã»ãšãããŒã°ã®å®å šãªãã¿ãŒã³:
function_start:
; === ããããŒã° ===
push rbp ; 1. åŒã³åºãå
rbpä¿å
mov rbp, rsp ; 2. æ°ããã¹ã¿ãã¯ãã¬ãŒã èšå®
; === 颿°æ¬äœ ===
; å®éã®åŠç...
; === ãšãããŒã° ===
leave ; 3. ã¹ã¿ãã¯ãã¬ãŒã 埩å
ret ; 4. åŒã³åºãå
ã«åŸ©åž°
ãªãã¹ã¿ãã¯ãã¬ãŒã ãå¿ èŠïŒ
-
颿°éã®ç¬ç«æ§
- å颿°ãç¬èªã®ã¹ã¿ãã¯é åãæã€
- ä»ã®é¢æ°ã®å€æ°ãšå¹²æžããªã
- å®å šãªé¢æ°åŒã³åºããå¯èœ
-
ããŒã«ã«å€æ°ã®ç®¡ç
push rbp mov rbp, rsp sub rsp, 32 ; 32ãã€ãã®ããŒã«ã«é åç¢ºä¿ ; ããŒã«ã«å€æ°ã¢ã¯ã»ã¹äŸ: mov qword [rbp-8], rax ; 1ã€ç®ã®ããŒã«ã«å€æ° mov qword [rbp-16], rbx ; 2ã€ç®ã®ããŒã«ã«å€æ°
-
ãããã¬ãµããŒã
- GDBãªã©ã®ãããã¬ãã¹ã¿ãã¯ãã¬ãŒã¹ãæ£ç¢ºã«è¡šç€º
- 颿°åŒã³åºãéå±€ã®ææ¡ã容æ
- ãã¬ãŒã¯ãã€ã³ãã§ã®å€æ°æ€æ»ãå¯èœ
å®è¡æã®ã¡ã¢ãªå€åäŸ:
颿°åŒã³åºãå:
rsp: 0x7fff12345678 rbp: 0x7fff12345698
push rbp å®è¡åŸ:
rsp: 0x7fff12345670 rbp: 0x7fff12345698
ã¹ã¿ãã¯: [0x7fff12345698] â ä¿åãããrbp
mov rbp, rsp å®è¡åŸ:
rsp: 0x7fff12345670 rbp: 0x7fff12345670
æ°ããã¹ã¿ãã¯ãã¬ãŒã 確ç«å®äº
cmp rsi, 0 ; check if divisor is zero
je .error ; if zero, jump to error handler
ãŒãé€ç®æ€åº:
-
cmp rsi, 0
: 逿°(divisor)ããŒããšæ¯èŒ -
je .error
: ãŒãã®å Žåããšã©ãŒãã³ãã©ãžãžã£ã³ã - CPU ãã©ã°ã¬ãžã¹ã¿ã®ZF(Zero Flag)ãå©çš
æ¡ä»¶ãžã£ã³ãã®è©³çް:
; cmpåœä»€ã®åäœ
cmp rsi, 0
; å
éšçã«ã¯: rsi - 0 ãèšç®ãããã©ã°ãèšå®
; ZF = 1 (rsi == 0ã®å Žå)
; ZF = 0 (rsi != 0ã®å Žå)
je .error
; Jump if Equal: ZF == 1ã®å Žåãžã£ã³ã
; ãŒãé€ç®ã確å®ã«æ€åº
mov rax, rdi ; dividend to rax
cqo ; sign extend rax to rdx:rax
idiv rsi ; signed division: rax = rax / rsi
é€ç®ã®æºå:
mov rax, rdi ; è¢«é€æ°ãraxã«èšå®
-
rdi
: 第1åŒæ° (è¢«é€æ°/dividend) -
rax
: é€ç®åœä»€çšã®ã¬ãžã¹ã¿
ç¬Šå·æ¡åŒµåŠç:
cqo ; Convert Quad to Oct
CQOåœä»€ã®è©³çŽ°è§£èª¬:
CQO (Convert Quad to Oct) ã®åºæ¬åäœ:
-
rax
ã¬ãžã¹ã¿ïŒ64ãããïŒã®ç¬Šå·ããããrdx
ã«æ¡åŒµ - 64ããã â 128ãããç¬Šå·æ¡åŒµãå®è¡
-
rdx:rax
ã¬ãžã¹ã¿ãã¢ã§128ãããå€ãæ§æ - 笊å·ä»ãé€ç®ïŒ
idiv
ïŒã«å¿ èŠãªååŠç
ãªãCQOãå¿ èŠãªã®ã:
idiv rsi ; 128ããã ÷ 64ããã = 64ããã
-
idiv
åœä»€ã¯128ãããè¢«é€æ°ãæåŸ - è¢«é€æ°ã¯
rdx:rax
ã¬ãžã¹ã¿ãã¢ã§è¡šçŸ -
rdx
ã«é©åãªç¬Šå·æ¡åŒµå€ãå¿ èŠ -
cqo
ã«ããæ£ãã128ãããå€ãæºå
ç¬Šå·æ¡åŒµã®åäœäŸ:
æ£æ°ã®å Žå:
rax = 0x000000000000000F (15)
cqoå®è¡åŸ:
rdx = 0x0000000000000000
rax = 0x000000000000000F
è² æ°ã®å Žå:
rax = 0xFFFFFFFFFFFFFFF1 (-15)
cqoå®è¡åŸ:
rdx = 0xFFFFFFFFFFFFFFFF
rax = 0xFFFFFFFFFFFFFFF1
笊å·ä»ãé€ç®å®è¡:
idiv rsi ; Integer Division (signed)
IDIVåœä»€ã®åäœ:
- å
¥å:
rdx:rax
(128ãããè¢«é€æ°),rsi
(64ããã逿°) - åºå:
rax
(å),rdx
(äœã) - 笊å·ä»ãæŽæ°é€ç®ãå®è¡
- ããŒããŠã§ã¢ã¬ãã«ã§é«éå®è¡
é€ç®çµæã®æ ŒçŽ:
äŸ: safe_divide(17, 3)
rdx:rax = 0x0000000000000000:0x0000000000000011 (17)
rsi = 0x0000000000000003 (3)
idivå®è¡åŸ:
rax = 0x0000000000000005 (å: 5)
rdx = 0x0000000000000002 (äœã: 2)
leave
ret
颿°ãšãããŒã°ã®è©³çŽ°è§£èª¬:
leaveåœä»€ã®å éšåäœ:
leave ; ãã®1åœä»€ã¯ä»¥äžãšå®å
šã«ç䟡:
; mov rsp, rbp ; 1. ã¹ã¿ãã¯ãã€ã³ã¿åŸ©å
; pop rbp ; 2. ããŒã¹ãã€ã³ã¿åŸ©å
leaveåœä»€ãå®è¡ããåŠç:
-
ã¹ã¿ãã¯ãã€ã³ã¿ã®åŸ©å (mov rsp, rbp)
å®è¡å: rsp = çŸåšäœçœ®, rbp = ãã¬ãŒã éå§äœçœ® å®è¡åŸ: rsp = rbp (ãã¬ãŒã éå§äœçœ®ã«æ»ã)
- 颿°å ã§äœ¿çšããã¹ã¿ãã¯é åãäžæ°ã«è§£æŸ
- ããŒã«ã«å€æ°ãäžæçãªããŒã¿ãã¯ãªã¢ããã
- ã¹ã¿ãã¯ãã€ã³ã¿ã颿°éå§æã®äœçœ®ã«æ»ã
-
ããŒã¹ãã€ã³ã¿ã®åŸ©å (pop rbp)
å®è¡å: ã¹ã¿ãã¯å é ã«ä¿åãããåŒã³åºãå ã®rbp å®è¡åŸ: rbp = åŒã³åºãå ã®å ã®rbpå€
- 颿°éå§æã«
push rbp
ã§ä¿åããå€ã埩å - åŒã³åºãå 颿°ã®ã¹ã¿ãã¯ãã¬ãŒã ã埩掻
- ãã¹ããã颿°åŒã³åºãã§ãæ£ç¢ºã«åŸ©å
- 颿°éå§æã«
ã¡ã¢ãªç¶æ ã®å€å:
leaveå®è¡å:
âââââââââââââââ â é«äœã¢ãã¬ã¹
â åŒã³åºãå
â
âââââââââââââââ€
â ä¿åãããrbpâ â ãã®å€ãrbpã«åŸ©å
ââââââââââââââ†â çŸåšã®rbp
â 颿°å
ã§ â
â 䜿çšãã â
â ããŒã¿ â â ãã®é åãè§£æŸããã
ââââââââââââââ†â çŸåšã®rsp
â â
âââââââââââââââ â äœäœã¢ãã¬ã¹
leaveå®è¡åŸ:
âââââââââââââââ â é«äœã¢ãã¬ã¹
â åŒã³åºãå
â
ââââââââââââââ†â 埩å
ãããrbp (åŒã³åºãå
)
â â â rspäœçœ® (颿°åŒã³åºãåã«æ»ã)
âââââââââââââââ â äœäœã¢ãã¬ã¹
retåœä»€ã®åäœ:
ret ; åŒã³åºãå
ãžã®åŸ©åž°
- ã¹ã¿ãã¯ããæ»ãã¢ãã¬ã¹ã
pop
- ãã®ã¢ãã¬ã¹ã«
jmp
- 颿°åŒã³åºãå ã®æ¬¡ã®åœä»€ããå®è¡ç¶ç¶
å®å šãªé¢æ°åŒã³åºãã»åŸ©åž°ãµã€ã¯ã«:
1. 颿°åŒã³åºã (call):
- æ»ãã¢ãã¬ã¹ãã¹ã¿ãã¯ã«push
- 颿°ã®éå§ã¢ãã¬ã¹ã«jump
2. 颿°éå§ (ããããŒã°):
- push rbp ; åŒã³åºãå
rbpä¿å
- mov rbp, rsp ; æ°ãã¬ãŒã èšå®
3. 颿°åŠç:
- å®éã®ã¿ã¹ã¯å®è¡
4. 颿°çµäº (ãšãããŒã°):
- leave ; ã¹ã¿ãã¯ãã¬ãŒã å®å
šåŸ©å
- ret ; åŒã³åºãå
ã«åŸ©åž°
leave䜿çšã®å©ç¹:
-
ã³ãŒãã®ç°¡æœæ§
; leaveäœ¿çš (1åœä»€) leave ; æå埩å (2åœä»€) mov rsp, rbp pop rbp
-
ãšã©ãŒé²æ¢
- 埩å åŠçã®é åºééããé²ã
- æåå®è£
ã§ã®
mov
ãšpop
ã®é åºãã¹ãåé¿ - æšæºçãªãã¿ãŒã³ãªã®ã§å¯èªæ§ãé«ã
-
ãããã¬äºææ§
- æšæºçãªé¢æ°ãã¬ãŒã æ§é
- GDBãªã©ã®ãããã¬ãæ£ç¢ºã«ã¹ã¿ãã¯ãã¬ãŒã¹è¡šç€º
- ãããã¡ã€ã©ããŒã«ãšã®äºææ§
æé©åãšã®é¢ä¿:
; ãã¬ãŒã ãã€ã³ã¿äžèŠãªå Žå (-fomit-frame-pointer)
simple_function:
; push rbp, mov rbp, rsp ã¯çç¥
; çŽæ¥åŠç
ret ; leaveäžèŠ
; ãã¬ãŒã ãã€ã³ã¿å¿
èŠãªå Žå
complex_function:
push rbp ; å¿
é
mov rbp, rsp ; å¿
é
; åŠç...
leave ; å¿
é
ret
ãã®ããã«leave
åœä»€ã¯ã颿°ã®ã¹ã¿ãã¯ãã¬ãŒã 管çãå¹ççãã€å®å
šã«è¡ãããã®éèŠãªåœä»€ã§ãã
.error:
push rax ; preserve registers
call __errno_location wrt ..plt
mov qword [rax], 22 ; set errno to EINVAL (22)
pop rax
mov rax, -1 ; return error value
leave
ret
push rax ; preserve registers
ãªãã¬ãžã¹ã¿ä¿åãå¿ èŠïŒ
-
__errno_location
åŒã³åºãã§rax
ãç Žå£ããã - å ã®å€ãä¿æããå¿ èŠãããïŒä»åã¯å®éã«ã¯äœ¿çšããªãããè¯ãå®è·µïŒ
- 颿°åŒã³åºãèŠçŽã®éµå®
call __errno_location wrt ..plt
mov qword [rax], 22 ; set errno to EINVAL (22)
__errno_location颿°:
- glibcæäŸã®ã·ã¹ãã 颿°
- çŸåšã®ã¹ã¬ããã®errno倿°ã®ã¢ãã¬ã¹ãè¿ã
- ãã«ãã¹ã¬ãã察å¿ã®errnoå®è£
PLT (Procedure Linkage Table):
wrt ..plt ; Position-independent code
PLTã®è©³çްã¡ã«ããºã :
PLT (Procedure Linkage Table) ã¯åçãªã³ã¯ã«ãããéèŠãªä»çµã¿ã§ãïŒ
-
åçãªã³ã¯ã®å¿ èŠæ§
call __errno_location ; çŽæ¥åŒã³åºãïŒäžå¯èœïŒ call __errno_location wrt ..plt ; PLTçµç±ïŒæ£ããæ¹æ³ïŒ
-
__errno_location
ã¯å ±æã©ã€ãã©ãª(glibc)å ã®é¢æ° - å®è¡æãŸã§ã¢ãã¬ã¹ã確å®ããªã
- PLTãå®è¡æã¢ãã¬ã¹è§£æ±ºãæ åœ
-
-
PLTã®åäœåç
ã³ã³ãã€ã«æ: ã¢ããªã±ãŒã·ã§ã³ â PLT ãšã³ã㪠â (æªè§£æ±º) å®è¡æåååŒã³åºã: ã¢ããªã±ãŒã·ã§ã³ â PLT â åçãªã³ã« â å®éã®é¢æ° â GOTã«ã¢ãã¬ã¹èšé² 2åç®ä»¥é: ã¢ããªã±ãŒã·ã§ã³ â PLT â GOT â å®éã®é¢æ°
-
wrt ..pltãã£ã¬ã¯ãã£ã
; NASMã®äœçœ®ç¬ç«ã³ãŒãæå® wrt ..plt ; "with respect to PLT"
- NASMã«å¯ŸããŠPLTçµç±ã§ã®ã¢ãã¬ã¹è§£æ±ºãæç€º
- Position Independent Code (PIC) ãçæ
- å ±æã©ã€ãã©ãªãšããŠå©çšå¯èœãªã³ãŒããäœæ
-
GOT (Global Offset Table) ãšã®é£æº
PLTãšã³ããªã®æ§é : âââââââââââââââââââ â jmp [GOT+offset]â â ååã¯åçãªã³ã«ãž â push index â 2åç®ä»¥éã¯çŽæ¥é¢æ°ãž â jmp resolver â âââââââââââââââââââ
-
é å»¶ãã€ã³ãã£ã³ã° (Lazy Binding)
// åååŒã³åºãæã®ã¿è§£æ±º call __errno_location wrt ..plt // â åçãªã³ã«ãå®éã®ã¢ãã¬ã¹ã解決 // â GOTã«ã¢ãã¬ã¹ãä¿å // â 以éã®åŒã³åºãã¯é«éå
-
ã»ãã¥ãªãã£ãšæé©å
; PLT䜿çšã®å©ç¹: ; - ASLR (Address Space Layout Randomization) å¯Ÿå¿ ; - å ±æã©ã€ãã©ãªã®å¹ççãªå©çš ; - ã¡ã¢ãªäœ¿çšéã®åæž
å®éã®ã¡ã¢ãªã¬ã€ã¢ãŠã:
å®è¡æã¡ã¢ãªé
眮:
ââââââââââââââââ â äœäœã¢ãã¬ã¹
â .text sectionâ (å®è¡ã³ãŒã)
ââââââââââââââââ€
â .plt section â (PLTãšã³ããªçŸ€)
ââââââââââââââââ€
â .got section â (GOTããŒãã«)
ââââââââââââââââ€
â å
±æã©ã€ãã©ãª â (glibcçãé«äœã¢ãã¬ã¹)
ââââââââââââââââ
- åçãªã³ã¯çšã®ã¢ãã¬ã¹è§£æ±º
- å ±æã©ã€ãã©ãªãšã®é©åãªé£æº
- ã¢ãã¬ã¹ç¬ç«ã³ãŒã(PIC)ã®å®çŸ
ãšã©ãŒã³ãŒãã®èšå®:
mov qword [rax], 22 ; EINVAL = 22
EINVAL (Invalid argument):
- ãšã©ãŒã³ãŒã22ã®æå³
- ç¡å¹ãªåŒæ°ãæž¡ãããå Žå
- ãŒãé€ç®ã¯ãç¡å¹ãªé€æ°ããšããŠé©å
æšæºãšã©ãŒã³ãŒãäžèЧ:
#define EINVAL 22 /* Invalid argument */
#define EDOM 33 /* Math argument out of domain */
#define ERANGE 34 /* Math result not representable */
#define EFAULT 14 /* Bad address */
pop rax
mov rax, -1 ; return error value
ãšã©ãŒæã®æ»ãå€:
-
-1
: æšæºçãªãšã©ãŒæ»ãå€ - Cæšæºã©ã€ãã©ãªã®æ £äŸã«åŸã
- æ£åžžãªé€ç®çµæãšæç¢ºã«åºå¥å¯èœ
.error:
neg rax ; make error code positive
push rax ; save error code
call __errno_location wrt ..plt
pop rdx ; restore error code
mov [rax], rdx ; set errno
mov rax, -1 ; return -1
.error:
push rax ; preserve registers
call __errno_location wrt ..plt
mov qword [rax], 22 ; set errno to EINVAL (22)
pop rax
mov rax, -1 ; return error value
çžéç¹ã®åæ:
-
ãšã©ãŒã³ãŒãã®æ±ã
- ft_write: ã·ã¹ãã ã³ãŒã«ããã®ãšã©ãŒã³ãŒãã䜿çš
- practice7: åºå®ã®ãšã©ãŒã³ãŒã(EINVAL)ãèšå®
-
ãšã©ãŒæ å ±ã®ååŸæ¹æ³
- ft_write: syscallã®æ»ãå€ãããšã©ãŒæ å ±ãååŸ
- practice7: äºåã«ãšã©ãŒæ¡ä»¶ãæ€åºããŠå¯Ÿå¿
-
å ±éãã¿ãŒã³
-
__errno_location
ã®åŒã³åºã - PLTãéããåçãªã³ã¯
- æ»ãå€ -1 ã®èšå®
-
åæç¶æ
:
- rdi = 17 (è¢«é€æ°)
- rsi = 3 (逿°)
å®è¡ãããŒ:
1. cmp rsi, 0 ; 3 != 0, ZF = 0
2. je .error ; ãžã£ã³ãããªã
3. mov rax, rdi ; rax = 17
4. cqo ; rdx = 0, rax = 17
5. idiv rsi ; rax = 5, rdx = 2
6. leave/ret ; æ»ãå€ rax = 5
åæç¶æ
:
- rdi = 10 (è¢«é€æ°)
- rsi = 0 (逿°)
å®è¡ãããŒ:
1. cmp rsi, 0 ; 0 == 0, ZF = 1
2. je .error ; .error ã«ãžã£ã³ã
3. push rax ; ã¬ãžã¹ã¿ä¿å
4. call __errno_location ; errno ã¢ãã¬ã¹ååŸ
5. mov [rax], 22 ; errno = EINVAL
6. pop rax ; ã¬ãžã¹ã¿åŸ©å
7. mov rax, -1 ; æ»ãå€ = -1
8. leave/ret ; ãšã©ãŒæ»ãå€ -1
-
ãšã©ãŒãã³ããªã³ã°èšèš
- äºåæ¡ä»¶ã®æ€èšŒ
- ãšã©ãŒç¶æ ã®é©åãªå ±å
- æšæºçãªãšã©ãŒåŠçãã¿ãŒã³
-
æ¡ä»¶åå²ããã°ã©ãã³ã°
- æ¯èŒåœä»€ã®æŽ»çš
- æ¡ä»¶ãžã£ã³ãã®é©åãªäœ¿çš
- ããã°ã©ã ãããŒã®å¶åŸ¡
-
ã·ã¹ãã ã€ã³ã¿ãŒãã§ãŒã¹
- errnoæ©æ§ã®çè§£
- æšæºã©ã€ãã©ãªãšã®é£æº
- APIèšèšã®åå
unsafe_divide:
mov rax, rdi
cqo
idiv rsi ; ãŒãé€ç®ã§å®è¡æãšã©ãŒ
ret
åé¡ç¹:
- ãŒãé€ç®ã§ããã°ã©ã ã¯ã©ãã·ã¥
- äºæããªãåäœ
- ãããã°å°é£
safe_divide:
cmp rsi, 0
je .error ; å®å
šãªãšã©ãŒåŠç
mov rax, rdi
cqo
idiv rsi
ret
.error:
; é©åãªãšã©ãŒåŠç
æ¹åç¹:
- 確å®ãªãšã©ãŒæ€åº
- é©åãªãšã©ãŒå ±å
- ããã°ã©ã ã®å®å®æ§åäž
advanced_divide:
; NULLãã€ã³ã¿ãã§ãã¯
test rdi, rdi
jz .null_error
; ãªãŒããŒãããŒãã§ãã¯
cmp rdi, 0x8000000000000000 ; LONG_MIN
jne .normal_check
cmp rsi, -1
je .overflow_error
.normal_check:
cmp rsi, 0
je .zero_div_error
; æ£åžžãªé€ç®åŠç
mov rax, rdi
cqo
idiv rsi
ret
.null_error:
call __errno_location wrt ..plt
mov qword [rax], 14 ; EFAULT
mov rax, -1
ret
.zero_div_error:
call __errno_location wrt ..plt
mov qword [rax], 22 ; EINVAL
mov rax, -1
ret
.overflow_error:
call __errno_location wrt ..plt
mov qword [rax], 34 ; ERANGE
mov rax, -1
ret
safe_float_divide:
; æµ®åå°æ°ç¹ãŒãé€ç®ãã§ãã¯
ucomisd xmm1, [zero_double]
je .float_error
divsd xmm0, xmm1
ret
.float_error:
call __errno_location wrt ..plt
mov qword [rax], 33 ; EDOM
; NaN ãè¿ã
movsd xmm0, [nan_value]
ret
section .data
zero_double: dq 0.0
nan_value: dq 0x7FF8000000000000 ; quiet NaN
debug_divide:
push rbp
mov rbp, rsp
sub rsp, 16 ; ããŒã«ã«å€æ°çš
; åŒæ°ãããŒã«ã«å€æ°ã«ä¿å
mov [rbp-8], rdi ; dividend
mov [rbp-16], rsi ; divisor
; ãããã°åºå
lea rdi, [debug_msg]
mov rsi, [rbp-8]
mov rdx, [rbp-16]
call printf
; ãšã©ãŒãã§ãã¯
cmp qword [rbp-16], 0
je .error
; é€ç®å®è¡
mov rax, [rbp-8]
cqo
idiv qword [rbp-16]
add rsp, 16
leave
ret
.error:
lea rdi, [error_msg]
call printf
; ãšã©ãŒåŠç...
section .data
debug_msg: db "Dividing %ld by %ld", 10, 0
error_msg: db "Error: Division by zero!", 10, 0
; ééã: ãšã©ãŒãã§ãã¯å¿ã
unsafe_divide:
mov rax, rdi
cqo
idiv rsi ; ãŒãé€ç®ã§ã¯ã©ãã·ã¥
ret
; ééã: cqo ãªã
wrong_divide:
cmp rsi, 0
je .error
mov rax, rdi
; cqo ãæããŠãã
idiv rsi ; äžæ£ãªçµæ
ret
; ééã: ã¬ãžã¹ã¿ä¿åãªã
.error:
; push rax ãæããŠãã
call __errno_location wrt ..plt
mov qword [rax], 22
; raxã®å
ã®å€ã倱ããã
ret
// main.c
extern long safe_divide(long dividend, long divisor);
#include <stdio.h>
#include <errno.h>
int main() {
long result;
// æ£åžžãªã±ãŒã¹
result = safe_divide(20, 4);
printf("20 / 4 = %ld\n", result);
// ãšã©ãŒã±ãŒã¹
errno = 0;
result = safe_divide(10, 0);
if (result == -1 && errno == 22) {
printf("Error: Division by zero detected\n");
}
return 0;
}
#define CHECK_DIVIDE(dividend, divisor, result) do { \
errno = 0; \
result = safe_divide(dividend, divisor); \
if (result == -1 && errno != 0) { \
fprintf(stderr, "Division error: %s\n", strerror(errno)); \
return -1; \
} \
} while(0)
int calculator() {
long result;
CHECK_DIVIDE(100, 5, result);
printf("Result: %ld\n", result);
return 0;
}
ãã®å®è£ ã«ãã以äžãçè§£ã§ããŸãïŒ
-
ä¿¡é Œæ§ã®é«ããœãããŠã§ã¢éçº
- äºæããªãå ¥åãžã®å¯Ÿå¿
- é©åãªãšã©ãŒå ±åæ©æ§
- ããã°ã©ã ã¯ã©ãã·ã¥ã®é²æ¢
-
æšæºçãªãšã©ãŒãã³ããªã³ã°
- errnoæ©æ§ã®å®è£ æ¹æ³
- Cæšæºã©ã€ãã©ãªãšã®äºææ§
- ã¯ãã¹ãã©ãããã©ãŒã 察å¿
-
ãããã°ãšã¡ã³ããã³ã¹
- ãšã©ãŒåå ã®ç¹å®æ¯æŽ
- åé¡ã®æ©æçºèŠ
- éçšæã®å®å®æ§åäž
ãã®ç·Žç¿ã«ãããå®çšçãªã·ã¹ãã ããã°ã©ãã³ã°ã«å¿ èŠãªãšã©ãŒãã³ããªã³ã°æè¡ã身ã«ã€ããå ç¢ãªã¢ããªã±ãŒã·ã§ã³éçºèœåãåäžããŸãã