PSX и Assembler

   Недавно меня вдруг приспичило познать, что же такое кодинг под консоли. Проблем с выбором приставки под которую я собирался программировать не было, ею стала - PSX.
   Давным давно, когда я был маленьким и у меня не было компьютера, я любил играть в игры. Сначала в NES затем и в PSX. На PSX я познал такие игры как Twisted Metal, Resident Evil, Dino Crisis, Duke Nukem, Red Alert, Parasite Eve и т.д. Всех больше мне приглянулся TM4, в который до сих пор играю, правда на эмуляторе. Еще тогда я мечтал создать свою игру, но отсутствие компьютера препятствовало этому делу. Теперь вернемся к современности. Недавно закачал Twisted Metal 2 и поиграл. Всплакнув от нахлынувших воспоминаний решил пощупать приставку поглубже( я не извращенец ).
   Данная статья является скорее переводом, но информация взята из разных источников.
   Начнем с первого появления приставки на прилавках магазинов. В Японии дата 3 декабря 1994, в США 9 сентября 1995, а в Европе 29 сентября 1995 года. Разработала приставку компания Sony.
  
Краткие технические характеристики:

   CPU( Central Processing Unit ):
     Процессор MIPS R3000A совместимый с ( R3051 ) 32-разрядный RISC, тактовая частота 33.8688 MHz.
     Произведен LSI Logic Corp по лицензированной технологии у SGI. Чип содержит Geometry Transformation Engine и Data Decompression Engine.
   Geometry Transformation Engine
     Устройство добавляющее инструкции, которые необходимы при работе с трехмерной графикой.
   Возможности:
    - 360 000 полигонов в секунду.
    - 180 000 текстурированных и освещенных полигонов в секунду.
   Data Decompression Engine
     Устройство для декомпрессии изображений и видео, поддерживает MJPEG и H.261 файлы.
   GPU( Graphics Processing Unit ):
     Чип для работы с двухмерной графикой.
   Возможности:
    - максимум 16.7 миллионов цветов.
    - от 256x224 до 640x480 разрешения экрана.
    - максимум 24 бита на пиксел.
    - текстурирование и Гуро-затенение.
    - максимум 4000 8x8 спрайтов.
   SPU( Sound Processing Unit ):
    - 24 канала частотой до 44.1 Khz.
   Память:
    - главное ОЗУ 2 Мб.
    - видео ОЗУ 1 Мб.
    - звуковое ОЗУ 512 Кб.
    - буффер CD-ROM 32 Кб.
    - размер BIOS 512 Кб.
    - карта памяти вмещает 128 Кб.
   CD-ROM:
    - скорость чтения 300 кб/c.
  
Ассемблерные инструкции:

   Описание регистров:
    - $zero ----- $0 ( всегда 0 )
    - $at ----- $1
    - $v0–$v1 ----- $2–$3
    - $a0–$a3 ----- $4–$7
    - $t0–$t7 ----- $8–$15
    - $s0–$s7 ----- $16–$23
    - $t8–$t9 ----- $24–$25
    - $k0–$k1 ----- $26–$27( зарезервированы для ядра )
    - $gp ----- $28( глобальный указатель )
    - $sp ----- $29( указатель стека )
    - $fp ----- $30( указатель фрейма )
    - $ra ----- $31( адрес возврата )

   Структура:
     cmd arg, ... // Пояснения.
       xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - 32 битный код команды

    - ADD - сложение двух операндов и запись в результат. С учетом знака.
       add a, b, c // a = b + c; a, b, c - регистры.
       0000 00bb bbbc cccc aaaa a000 0010 0000
    - ADDU - сложение двух операндов и запись в результат. Без учета знака.
       addu a, b, c // a = b + c; a, b, c - регистры.
       0000 00bb bbbc cccc aaaa a000 0010 0001
    - ADDI - сложение двух операндов и запись в результат. С учетом знака.
       addi a, b, c // a = b + c; a, b - регистры, c - значение.
       0010 00bb bbba aaaa cccc cccc cccc cccc
    - ADDIU - сложение двух операндов и запись в результат. Без учета знака.
       addiu a, b, c // a = b + c; a, b - регистры, c - значение.
       0010 01bb bbba aaaa cccc cccc cccc cccc
    - AND - побитовое and.
       and a, b, c // a = b & c; a, b, c - регистры.
       0000 00bb bbbc cccc aaaa a000 0010 0100
    - ANDI - побитовое and.
       andi a, b, c // a = b & c; a, b - регистры; c - значение.
       0011 00bb bbba aaaa cccc cccc cccc cccc
    - BEQ - условный переход. Если операнды равны.
       beq a, b, offset // если ( a == b ) переход на offset; a, b - регистры, offset - адрес.
       0001 00aa aaab bbbb oooo oooo oooo oooo
    - BGEZ - условный переход. Если операнд больше или равен 0.
       bgez a, offset // если ( a >= 0 ) переход на offset; a - регистр, offset - адрес.
       0000 01aa aaa0 0001 oooo oooo oooo oooo
    - BGEZAL - условный переход. Если операнд больше 0. Сохранение адреса возврата в $31.
       bgezal a, offset // если ( a >= 0 ) переход на offset; a - регистр, offset - адрес.
       0000 01aa aaa1 0001 oooo oooo oooo oooo
    - BGTZ - условный переход. Если операнд больше 0.
       bgtz a, offset // если ( a > 0 ) переход на offset; a - регистр, offset - адрес.
       0001 11aa aaa0 0000 oooo oooo oooo oooo
    - BLEZ - условный переход. Если операнд меньше или равен 0.
       blez a, offset // если ( a <= 0 ) переход на offset; a - регистр, offset - адрес.
       0001 10aa aaa0 0000 oooo oooo oooo oooo
    - BLTZ - условный переход. Если операнд меньше 0.
       bltz a, offset // если ( a < 0 ) переход на offset; a - регистр, offset - адрес.
       0000 01aa aaa0 0000 oooo oooo oooo oooo
    - BLTZAL - условный переход. Если операнд меньше 0. Сохранение адреса возврата в $31.
       bltzal a, offset // если ( a < 0 ) переход на offset; a - регистр, offset - адрес.
       0000 01aa aaa1 0000 oooo oooo oooo oooo
    - BNE - условный переход. Если операнды не равны.
       bne a, b, offset // если ( a != b ) переход на offset; a, b - регистры, offset - адрес.
       0001 01aa aaab bbbb oooo oooo oooo oooo
    - DIV - деление. $LO - записывается целый результат, $HI - остаток.
       div a, b // $LO = a / b, $HI = a % b; a, b - регистры.
       0000 00aa aaab bbbb 0000 0000 0001 1010
    - DIVU - деление. $LO - записывается целый результат, $HI - остаток. Без учета знака.
       divu a, b // $LO = a / b, $HI = a % b; a, b - регистры.
       0000 00aa aaab bbbb 0000 0000 0001 1011
    - J - прыжок.
       j offset // переход на offset; offset - метка.
       0000 10oo oooo oooo oooo oooo oooo oooo
    - JAL - прыжок. Сохранение адреса возврата в $31.
       jal offset // переход на offset; offset - метка.
       0000 11oo oooo oooo oooo oooo oooo oooo
    - JR - прыжок. Переход на адрес, указанный в регистре.
       jr a // переход на a; a - регистр.
       0000 00aa aaa0 0000 0000 0000 0000 1000
    - LB - запись байта из указанного адреса в регистр.
       lb a, offset( b ) // a = память( b + offset ); a, b - регистры, offset - адрес.
       1000 00bb bbba aaaa oooo oooo oooo oooo
    - LBU - запись байта из указанного адреса в регистр. Значение без знака.
       lbu a, offset( b ) // a = память( b + offset ); a, b - регистры, offset - адрес.
       1001 00bb bbba aaaa oooo oooo oooo oooo
    - LH - запись половины слова( 16 бит ) из указанного адреса в регистр.
       lh a, offset( b ) // a = память( b + offset ); a, b - регистры, offset - адрес.
       1000 01bb bbba aaaa oooo oooo oooo oooo
    - LHU - запись половины слова( 16 бит ) из указанного адреса в регистр. Значение без знака.
       lhu a, offset( b ) // a = память( b + offset ); a, b - регистры, offset - адрес.
       1001 01bb bbba aaaa oooo oooo oooo oooo
    - LUI - запись значения в регистр со двигом влево на 16 бит.
       lui a, b // a = ( b << 16 ); a - регистр, b - значение.
       0011 1100 000a aaaa bbbb bbbb bbbb bbbb
    - LW - запись слова из указанного адреса в регистр.
       lw a, offset( b ) // a = память( b + offset ); a, b - регистры, offset - адрес.
       1000 11bb bbba aaaa oooo oooo oooo oooo
    - LWU - запись слова из указанного адреса в регистр. Значение без знака.
       lwu a, offset( b ) // a = память( b + offset ); a, b - регистры, offset - адрес.
       1001 11bb bbba aaaa oooo oooo oooo oooo
    - MFHI - копирование содержимого $HI в указанный регистр.
       mfhi a // a = $HI; a - регистр.
       0000 0000 0000 0000 aaaa a000 0001 0000
    - MFLO - копирование содержимого $LO в указанный регистр.
       mflo a // a = $LO; a - регистр.
       0000 0000 0000 0000 aaaa a000 0001 0010
    - MTHI - копирование содержимого указанного регистра в $HI.
       mthi a // $HI = a; a - регистр.
       0000 00aa aaa0 0000 0000 0000 0001 0001
    - MTLO - копирование содержимого указанного регистра в $LO.
       mtlo a // $LO = a; a - регистр.
       0000 00aa aaa0 0000 0000 0000 0001 0011
    - MULT - умножение операндов и запись результата в $LO.
       mult a, b // $LO = a * b; a, b - регистры.
       0000 00aa aaab bbbb 0000 0000 0001 1000
    - MULTU - умножение операндов и запись результата в $LO. Без знака.
       multu a, b // $LO = a * b; a, b - регистры.
       0000 00aa aaab bbbb 0000 0000 0001 1001
    - NOOP - то самое. Ничего не делает.
       noop // Ничего.
       0000 0000 0000 0000 0000 0000 0000 0000
    - OR - побитовое or.
       or a, b, c // a = b | c; a, b, c - регистры.
       0000 00bb bbbc cccc aaaa a000 0010 0101
    - ORI - побитовое or.
       ori a, b, c // a = b | c; a, b - регистры, c - значение.
       0011 01bb bbba aaaa cccc cccc cccc cccc
    - SB - запись байта из регистра в память.
       sb a, offset( b ) // память( b + offset ) = a; a, b - регистры, offset - адрес..
       1010 00bb bbba aaaa oooo oooo oooo oooo
    - SH - запись полуслова( 16 бит ) из регистра в память.
       sh a, offset( b ) // память( b + offset ) = a; a, b - регистры, offset - адрес..
       1010 01bb bbba aaaa oooo oooo oooo oooo
    - SLL - запись в регистр результата, получившегося сдвигом регистра на указанное значение влево.
       sll a, b, c // a = b << c; a, b - регистры, c - значение..
       0000 0000 000b bbbb aaaa accc cc00 0000
    - SLLV - запись в регистр результата, получившегося сдвигом регистра на указанное значение влево.
       sllv a, b, c // a = b << c; a, b, c - регистры..
       0000 00cc cccb bbbb aaaa a000 0000 0100
    - SLT - присваивание регистру 1 или 0.
       slt a, b, c // если( b < c ) a = 1 иначе a = 0; a, b, c - регистры.
       0000 00bb bbbc cccc aaaa a000 0010 1010
    - SLTI - присваивание регистру 1 или 0.
       slti a, b, c // если( b < c ) a = 1 иначе a = 0; a, b - регистры; c - значение.
       0010 10bb bbba aaaa cccc cccc cccc cccc
    - SLTIU - присваивание регистру 1 или 0. Без знака.
       sltiu a, b, c // если( b < c ) a = 1 иначе a = 0; a, b - регистры; c - значение.
       0010 11bb bbba aaaa cccc cccc cccc cccc
    - SLTU - присваивание регистру 1 или 0. Без знака.
       sltu a, b, c // если( b < c ) a = 1 иначе a = 0; a, b, c - регистры.
       0000 00bb bbbc cccc aaaa a000 0010 1011
    - SRL - запись в регистр результата, получившегося сдвигом регистра на указанное значение вправо.
       srl a, b, c // a = b >> c; a, b - регистры, c - значение..
       0000 0000 000b bbbb aaaa accc cc00 0010
    - SRLV - запись в регистр результата, получившегося сдвигом регистра на указанное значение вправо.
       srlv a, b, c // a = b >> c; a, b, c - регистры..
       0000 0000 000c cccc bbbb baaa aa00 0110
    - SUB - запись в регистр разности двух регистров.
       sub a, b, c // a = b - c; a, b, c - регистры.
       0000 00bb bbbc cccc aaaa a000 0010 0010
    - SUBU - запись в регистр разности двух регистров. Без знака.
       subu a, b, c // a = b - c; a, b, c - регистры.
       0000 00bb bbbc cccc aaaa a000 0010 0011
    - SW - запись слова из регистра в память.
       sw a, offset( b ) // память( b + offset ) = a; a, b - регистры, offset - адрес..
       1010 11bb bbba aaaa oooo oooo oooo oooo
    - XOR - побитовое xor.
       xor a, b, c // a = b ^ c; a, b, c - регистры.
       0000 00bb bbbc cccc aaaa a000 0010 0110
    - XORI - побитовое xor.
       xori a, b, c // a = b ^ c; a, b - регистры, c - значение.
       0011 10bb bbba aaaa cccc cccc cccc cccc

   Я рассмотрел полностью только команду ADD, другие команды аналогичны например SUB, SUBI, SUBU, SBIU.

   Ссылки:
Википедия Playstation
Много чего вкусного

Статью написал faceH0r 15.08.2006
Используются технологии uCoz