---
# System prepended metadata

title: 使用 LLVM IR 語言，打印出一個帶有參數的字串

---

# 使用 LLVM IR 語言，打印出一個帶有參數的字串
完整的code:

```
; ModuleID = 'example'
source_filename = "example"

@formatString = private constant [15 x i8] c"Hello, %s!\n\00"

declare i32 @printf(i8*, ...)

define i32 @main(i32 %argc, i8** %argv) {
  entry:
    %str = getelementptr [15 x i8], [15 x i8]* @formatString, i32 0, i32 0
    %call = call i32 (i8*, ...) @printf(i8* %str, i8* %argv)
    ret i32 0
}

```


---

```
; ModuleID = 'example'
source_filename = "example"
```
LLVM IR 檔案的元數據（Metadata）

它們指定了模組的 ID 和來源檔案的名稱


---

```
@formatString = private constant [15 x i8] c"Hello, %s!\n\00"
```
聲明一個私有的常數 formatString，它是一個包含字串 "Hello, %s!\n" 的字元陣列

[15 x i8] 表示這是一個長度為 15 的字元陣列

c"Hello, %s!\n\00" 表示這是一個以字元串形式表示的常數

---
```
declare i32 @printf(i8*, ...)
```
聲明一個外部函式 printf，它接受一個 i8*（指向字元的指標）作為參數，並具有變參（variadic）參數列表

---
```
define i32 @main(i32 %argc, i8** %argv) {
```
定義 main 函式，它接受兩個參數 argc 和 argv，其中 argc 是一個整數，argv 是一個指向指向字元的指標的指標（C 語言中的命令列參數）

---
```
entry:
```
標記一個基本區塊（Basic Block）的起始點，它的名稱是 entry


---

```
%str = getelementptr [15 x i8], [15 x i8]* @formatString, i32 0, i32 0
```
這一行使用 getelementptr 指令，計算 formatString 字串的位址。

它的第一個參數 [15 x i8] 是源陣列的類型

第二個參數 [15 x i8]* @formatString 是源陣列的指標

第三個和第四個參數 i32 0 是計算索引值的偏移量，這裡都是 0，表示獲取第一個元素的位址
```
%call = call i32 (i8*, ...) @printf(i8* %str, i8* %argv)
```
這一行使用 call 指令呼叫 printf 函式

i32 是呼叫的返回值類型，(i8*, ...) 是函式的參數列表類型

@printf 是函式的名稱

i8* %str 和 i8* %argv 是實際的參數，分別將 %str 和 %argv 傳遞給 printf 函式

---

```
ret i32 0
```
使用 ret 指令返回整數值 0

這表示 main 函式的執行結束並返回 0，這通常用於表示程式正常結束
## 來源
> https://chat.openai.com/?model=text-davinci-002-render-sha