昨天的那篇很麻煩吧!!所以從聰明如我只會用第一種方法喔(畢竟我們要善用電腦對吧
題目:ARMssembly 1
題目的意思我想了好久,他的意思是要找到一個數(k)使得./chall_1 k 2 3要顯示you win!
他的description有夠不清楚,害我卡好久
.arch armv8-a
.file "chall_1.c"
.text
.align 2
.global func
.type func, %function
func:
sub sp, sp, #32 // sp 往下分配32個Byte給堆疊
str w0, [sp, 12] // 將w0的值 (58)存入地址[sp, 12]
mov w0, 58 // 將w0的值設為58(這裡是將58設為一個固定值,所以你的arg1是多少,並不會影響這裡的58)
str w0, [sp, 16] // 將w0的值 (58)存入地址[sp, 16]
mov w0, 2 // 將w0的值設為2
str w0, [sp, 20] // 將w0的值 (2)存入地址[sp, 20]
mov w0, 3 // 將w0的值設為3
str w0, [sp, 24] // 將w0的值 (3)存入地址[sp, 20]
ldr w0, [sp, 20] // 將[sp, 20]的值 (2)載入w0
ldr w1, [sp, 16] // 將[sp, 16]的值 (58)載入w1
lsl w0, w1, w0 // 對w1進行左移w0個(w0 = w1 << w0)
str w0, [sp, 28] // 將w0的值 (232)存入地址[sp, 28]
ldr w1, [sp, 28] // 將[sp, 28]的值 (232)載入w1
ldr w0, [sp, 24] // 將[sp, 24]的值 (3)載入w1
sdiv w0, w1, w0 // 進行整數除法w0 = w1//w0(232//3 = 77)
str w0, [sp, 28] // 將w0的值 (77)存入地址[sp, 28]
ldr w1, [sp, 28] // 將[sp, 28]的值 (77)載入w1
ldr w0, [sp, 12] // 將[sp, 12]的值 (58)載入w0
sub w0, w1, w0 // w0 = w1 - w0 (w0 = 77-58 = 19)
str w0, [sp, 28] // 將w0的值 (19)存入地址[sp, 28]
ldr w0, [sp, 28] // 將[sp, 28]的值 (19)載入w1
add sp, sp, 32 // 釋放為該函數分配的堆疊空間
ret // 返回呼叫點
.size func, .-func
.section .rodata
.align 3
.LC0:
.string "You win!"
.align 3
.LC1:
.string "You Lose :("
.text
.align 2
.global main
.type main, %function
main:
stp x29, x30, [sp, -48]! // 保存鏈接寄存器 (x30) 和幀指標 (x29),
//並分配 48 Byte堆疊空間
add x29, sp, 0 // 設置新的幀指標
str w0, [x29, 28] // 把w0的值給 x29+28 的地址 (這是輸入的參數 (58))
str x1, [x29, 16] // 把x1的值給 x29+16 的地址 (這是輸入的參數 (2))
ldr x0, [x29, 16] // 加載指向命令列參數的指針(即 argv)
add x0, x0, 8 // 跳過第一個參數,因為 argv[0] 是程式名稱
// 在 64 位元的 ARMv8 架構中,指針的大小是 8 Byte,因此 argv 中每個元素
// (每個字串的指針)都佔用 8 Byte。
ldr x0, [x0] // 加載 argv[1]
bl atoi // 將 argv[1] 轉換為整數,
// 可以查看https://developer.arm.com/documentation/101655/0961/Cx51-User-s-Guide/Library-Reference/Reference/atoi
str w0, [x29, 44] // 將轉換後的整數結果存入 x29 + 44
ldr w0, [x29, 44] // 加載轉換後的整數
// 要做這種看似無意義的事,其實是為了保證w0的資料不要被任何意外給洗掉
bl func // 呼叫func函式(這時w0 = 58)
cmp w0, 0 // w0 = 19 19-0>0 (CF=0 ,ZF=0)
bne .L4 // 當結果不等於0(也就是ZF=0)時跳到.L4
//當不符合bne則執行以下
adrp x0, .LC0 //準備一個字符串(.LC0)
add x0, x0, :lo12:.LC0 // x0 = x0 + .LC0(以顯示 "You Win! :(" 的信息。)
bl puts
b .L6
.L4:
adrp x0, .LC1 //adrp可以上網查一下,簡單來說獲取 .LC1 的頁面基址,存入 x0
add x0, x0, :lo12:.LC1 // x0 = x0 + .LC1 的低12位,獲取完整地址
bl puts
// 白話文:這些指令的作用是準備一個字符串(.LC1)並將其傳遞給 puts 函數,
// 以顯示 "You Lose :(" 的信息。
// 由此可知只要不符合bne .L4 即可跳過這裡
.L6:
nop
ldp x29, x30, [sp], 48
ret
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0"
.section .note.GNU-stack,"",@progbits
後記:
哭慘,結果都要不只要執行,還要了解程式碼,我的命都沒了🫠🫠這題好可怕,解開後還要計算,對我是蠻不輕鬆的,這題搞了好久最後的reverse還有點迷糊,我還在試著完全理解中,完全是通靈啊,我的媽