pretty code

2018年9月20日 星期四

x86 assembly in Linux - part 3

雖然 "Programming from the Ground Up" 還沒看完
在知道了如何呼叫 linux system call 後 (exit)
便想找 1 個簡單的 system call 來試試

看來看去 mkdir 算是相對簡單的
不過卻讓我卡了 2 天

直到今天才恍然大悟自己錯在哪裡
原來我只顧著 create directory
卻沒有 call exit system call
難怪死得不明不白

.section .data
name:
    .string "MK"

.section .text

.global _start

_start:
    movl $39, %eax
    movl $name, %ebx
    movl $0777, %ecx
    int $0x80

    movl $1, %eax
    movl $0, %ebx
    int $0x80

x86 assembly in Linux - part 2

"Programming from the Ground Up" 的作者建議寫組語時
最好是拿紙筆把要用到的暫存器安排一下
寫起 code 來會比較順暢

昨天回家洗澡時就想到
part 1 的 example 做了一些很不必要的動作
也多用到一些不必要的暫存器

舉例來說
%ebx 存起的是 memory address
也是我存放要比較整數的 list (array)

原本 for loop 都會用 %edi 來當 index variable
但在這個 case 其實是不必要的
因為我們本來就可以對暫存器直接做加減

start_loop:
    incl %edi

    movl $4, %edx
    imull %edi, %edx
    addl %ebx, %edx

start_loop:
    addl $4, %ebx

2018年9月19日 星期三

x86 assembly in Linux - part 1

目前看的書是網路很推薦的 "Programming from the Ground Up"
由於這本書介紹的是 32 位元的組語寫法
故在編譯成 64 位元的 code 時會有問題

此時需指定 --32 to as and -m elf_i386 to ld

as source.s --32 -o source.o
ld source.o -m elf_i386 -o source.out

另外,如果在 call function 時,想把 label's address pass to function
在 label 前面,需加上 "$"

底下是個 example,max function 會幫忙把資料組裡的最大值找出
並將回傳值放進 %eax register

.section .data
list:
    .long 31,2,199,7,0

.section .text

.global _start

_start:

    pushl $list
    call max
    addl $4, %esp

    movl %eax, %ebx
    movl $1, %eax
    int $0x80

.type max,@function
max:
    pushl %ebp
    movl %esp, %ebp

    movl 8(%ebp), %ebx

    movl $0, %edi

    movl $4, %edx
    imull %edi, %edx
    addl %ebx, %edx
    movl (%edx), %eax

start_loop:
    incl %edi

    movl $4, %edx
    imull %edi, %edx
    addl %ebx, %edx
    movl (%edx), %ecx

    cmpl $0, %ecx
    je end_loop

    cmpl %eax, %ecx
    jle start_loop

    movl %ecx, %eax
    jmp start_loop

end_loop:
    movl %ebp, %esp
    popl %ebp
    ret

2018年9月13日 星期四

big-endian and little endian

雖然知道這個的不同
但每次都會忘記記憶體位置的順序
乾脆畫了一個圖來幫助記憶

大概只有 3 個重點
1. 計憶體位置是由低到高
2. 最高位元的資料 (0x12) 先擺就是 big-endian
3. 相反就是 little-endian



2018年8月28日 星期二

Javascript Array fill function


var result = Array(5).fill(['-', '-']);

console.log('before', result);

result[0][1] = 'modify result[0]';

console.log('after ', result);


如果 fill 傳進去的是 1 個物件
如上例中的 ['-', '-']

最後 result array 裡面的元素
都會是同 1 個物件的 reference

這會造成明明只是要改 1 個 element
卻變成 5 個 element 都一起生效

真是 1 個神奇的 bug

2018年8月24日 星期五

startup.nsh in UEFI Shell

UEFI Shell 下有一個開機自動執行 tool 的方式,其方式類似 DOS 的 AUTOEXEC.BAT,只是檔名為 startup.nsh。

底下是 UEFI Shell Spec 2.2 的說明:

When executing startup.nsh, the shell will search for it first in the directory where the shell itself was launched. If it cannot find the startup.nsh file in that directory or it was not launched from a file system, it will search the execution path defined by the environment variable PATH.
 
由上可以得知,正常放進 USB 裡的 Shell 會位於 EFI\BOOT\,故只要將 startup.nsh 置於此處便可以自動執行。

另外,則是要看 PATH 環境變數是否有定義,Shell 會去裡面對應的位置去尋找 startup.nsh 來執行。

這也解釋了為什麼有些電腦 startup.nsh 不放在 EFI\BOOT\ 便不會自動執行,那是因為系統並沒有 PATH 的變數存在。

2018年8月23日 星期四

Delete file in C

最近分別需要在 Windwos, UEFI, DOS 撰寫同樣的 tool
趁著寫完的空檔,整理一下之前沒有注意到的小細節

在這 3 個系統中,我共用了大部份的 code,只有針對系統的差異做 porting
其中我需要 1 個砍檔案的 function (unlink)

最早我是先在 UEFI 使用這個功能
原本以為只有 UEFI 有

後來在陸續 porting 到 Windows and DOS 時
才發現大家都有這個函數

上網查了一下
這個不是 standard c
而是 POSIX 標準
難怪我的 gcc 也會有 (Windows)

底下是 3 個環境 include header file 的位置
UEFI(UDK code) - <sys/EfiSysCall.h>
Windows(TDM GCC) - <io.h>
DOS(Open Watcom) - <io.h>