vault backup: 2025-04-18 23:10:56
This commit is contained in:
123
PERSONAL PROJECTS/PS1 DOCS/PSX code inline asm.md
Normal file
123
PERSONAL PROJECTS/PS1 DOCS/PSX code inline asm.md
Normal file
@@ -0,0 +1,123 @@
|
||||
Вот готовая программа для **PlayStation 1**, которая использует **MIPS-ассемблерные вставки** для сложения двух чисел через указатели. Результат возвращается в переменную основной программы.
|
||||
|
||||
---
|
||||
|
||||
### **1. Полный код (MAIN.C)**
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <libetc.h>
|
||||
|
||||
// Объявляем ассемблерную функцию
|
||||
int add_numbers_asm(int *a, int *b, int *result);
|
||||
|
||||
int main() {
|
||||
int num1 = 5;
|
||||
int num2 = 7;
|
||||
int result = 0;
|
||||
|
||||
// Вызываем ассемблерную функцию с указателями
|
||||
add_numbers_asm(&num1, &num2, &result);
|
||||
|
||||
// Выводим результат
|
||||
FntPrint("Result: %d + %d = %d\n", num1, num2, result);
|
||||
FntFlush(-1);
|
||||
|
||||
while (1) {
|
||||
VSync(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Реализация на MIPS-ассемблере
|
||||
int add_numbers_asm(int *a, int *b, int *result) {
|
||||
int ret;
|
||||
asm volatile (
|
||||
"lw $t0, 0(%1) \n" // Загружаем *a в $t0
|
||||
"lw $t1, 0(%2) \n" // Загружаем *b в $t1
|
||||
"add $t2, $t0, $t1 \n" // Складываем: $t2 = $t0 + $t1
|
||||
"sw $t2, 0(%3) \n" // Сохраняем результат по адресу *result
|
||||
"move %0, $t2 \n" // Возвращаем результат через регистр
|
||||
: "=r" (ret) // Выходные операнды
|
||||
: "r" (a), "r" (b), "r" (result) // Входные операнды
|
||||
: "$t0", "$t1", "$t2" // Разрушаемые регистры
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **2. Как это работает?**
|
||||
1. **Передача указателей в ассемблер**
|
||||
Функция `add_numbers_asm` принимает три указателя:
|
||||
- `a` — адрес первого числа,
|
||||
- `b` — адрес второго числа,
|
||||
- `result` — адрес для сохранения результата.
|
||||
|
||||
2. **Ассемблерная вставка** (`asm volatile`):
|
||||
- `lw` — загружает значения из памяти по указателям.
|
||||
- `add` — складывает числа.
|
||||
- `sw` — сохраняет результат по адресу `result`.
|
||||
- `move` — возвращает значение через регистр.
|
||||
|
||||
3. **Доступ к результату**
|
||||
Результат будет:
|
||||
- В переменной `result` (через указатель).
|
||||
- В возвращаемом значении функции (если нужно).
|
||||
|
||||
---
|
||||
|
||||
### **3. Компиляция и запуск**
|
||||
1. Скомпилируйте через **PsyQ SDK**:
|
||||
```bash
|
||||
ccpsx MAIN.C -o ADD_DEMO.EXE
|
||||
```
|
||||
|
||||
2. Запишите на диск и запустите на эмуляторе или консоли.
|
||||
На экране появится:
|
||||
```
|
||||
Result: 5 + 7 = 12
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **4. Важные нюансы**
|
||||
- **Регистры MIPS**:
|
||||
- `$t0`–`$t9` — временные регистры (можно использовать без сохранения).
|
||||
- `$s0`–`$s7` — должны сохраняться (если используются).
|
||||
|
||||
- **Разрушаемые регистры**:
|
||||
Указаны в конце `asm volatile` (чтобы компилятор не использовал их для оптимизации).
|
||||
|
||||
- **Опасность**:
|
||||
Если передать **неверные указатели**, PS1 уйдёт в **краш** (нет защиты памяти).
|
||||
|
||||
---
|
||||
|
||||
### **5. Пример с глобальными переменными**
|
||||
Если нужно работать с глобальными переменными напрямую:
|
||||
```c
|
||||
int global_num1 = 10;
|
||||
int global_num2 = 20;
|
||||
|
||||
void add_globals_asm() {
|
||||
asm volatile (
|
||||
"la $t0, global_num1 \n" // Загружаем адрес global_num1
|
||||
"lw $t1, 0($t0) \n" // Читаем значение
|
||||
"la $t0, global_num2 \n"
|
||||
"lw $t2, 0($t0) \n"
|
||||
"add $t1, $t1, $t2 \n"
|
||||
"sw $t1, 0($t0) \n" // Сохраняем сумму в global_num2
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **6. Итог**
|
||||
- **Ассемблерные вставки** дают полный контроль над железом PS1.
|
||||
- **Указатели** передаются через регистры (`$a0`–`$a3` в MIPS).
|
||||
- **Результат** можно получить через память или возвращаемое значение.
|
||||
|
||||
Этот подход используется в оптимизированных частях игр (например, в рендеринге или физике).
|
||||
Reference in New Issue
Block a user