[18:17] <+SiberianSTAR> Assembly is a low-level programming language where each instruction corresponds to CPU op-code
[18:19] <+SiberianSTAR> Every CPU architecture has different set of opcodes and instructions, an op-code is an instruction that the CPU can understand
[18:20] <+SiberianSTAR> Every mips opcode is formed by 32 bits
[18:22] <+SiberianSTAR> This was the introduction
[18:23] <+SiberianSTAR> You can see the memory like a big matrix of bytes, where each byte is addressed with a 32bits value
[18:23] <+SiberianSTAR> The first byte is 0x0000000, the second is 0x00000001 and so on
[18:23] <+SiberianSTAR> A byte is formed by 8 bits, where each bits can be 1 or 0, on or off
[18:24] <+SiberianSTAR> An 8 bits value can store a number between 0 and 255, 2^0 - 2^8 - 1
[18:25] <+SiberianSTAR> On intel CPU the values are stored in the little-endian form, so the MSB (most significant byte) is the last byte
[18:25] <+SiberianSTAR> like
[18:25] <+SiberianSTAR> 0x12345678 - in memory is 0x78563412
[18:26] <+SiberianSTAR> Converting a number from hex to decimal is simple
[18:26] <+SiberianSTAR> Hexdecimal has 16 digits, 0-9 A-F
[18:26] <+SiberianSTAR> A = 10, B = 11, C = 12, D = 13, E = 14, F = 15
[18:27] <+SiberianSTAR> to convert for example 0xAA into Decimal you have to do 16^1 * A + 16^0 * A
[18:27] <+SiberianSTAR> A = 10 so, the number is 16*10 + 10 = 170 some more
[18:28] <+SiberianSTAR> The simpler operation that a CPU can perform between numbers are called bitwise-operations
[18:29] <+SiberianSTAR> The most common bitwise operation are OR, AND, NOT and XOR
[18:29] <+SiberianSTAR> they operate directly to each binary digit of a value
[18:29] <+SiberianSTAR> for example
[18:30] <+SiberianSTAR> OR
[18:30] <+SiberianSTAR> in1 in2 out
[18:30] <+SiberianSTAR> -----------
[18:30] <+SiberianSTAR> 0 0 0
[18:30] <+SiberianSTAR> 0 1 1
[18:30] <+SiberianSTAR> 1 0 1
[18:30] <+SiberianSTAR> 1 1 1
[18:30] <+SiberianSTAR> Takes as example the values 0xAA, 0x45
[18:31] <+SiberianSTAR> the binary rapresentation of the two values are 10101010 (0xAA) 01000101 (0x45)
[18:32] <+SiberianSTAR> An OR is a sum without the carry
[18:33] <+SiberianSTAR> Another bitwise logic operation is AND
[18:33] <+SiberianSTAR> in1 in2 out
[18:33] <+SiberianSTAR> -----------
[18:33] <+SiberianSTAR> 0 0 0
[18:33] <+SiberianSTAR> 0 1 0
[18:33] <+SiberianSTAR> 1 0 0
[18:33] <+SiberianSTAR> 1 1 1
[18:33] <+SiberianSTAR> And returns TRUE only if both bits are TRUE
[18:34] <+SiberianSTAR> In most cases AND is used to get only certain digits of an hex-number
[18:34] <+SiberianSTAR> for example
[18:34] <+SiberianSTAR> if you have
[18:34] <+SiberianSTAR> 0xABCD
[18:34] <+SiberianSTAR> but you want to get only the first and the last digit
[18:35] <+SiberianSTAR> you may do
[18:35] <+SiberianSTAR> 0xABCD AND 0xF00F
[18:35] <+SiberianSTAR> the output number will be 0XA00D
[18:35] <+SiberianSTAR> XOR is one of the most important bitwise logic operation
[18:35] <+SiberianSTAR> XOR means Exclusive-OR
[18:35] <+SiberianSTAR> It return TRUE only if the two bits are different
[18:36] <+SiberianSTAR> XOR
[18:36] <+SiberianSTAR> in1 in2 out
[18:36] <+SiberianSTAR> -----------
[18:36] <+SiberianSTAR> 0 0 0
[18:36] <+SiberianSTAR> 0 1 1
[18:36] <+SiberianSTAR> 1 0 1
[18:36] <+SiberianSTAR> 1 1 0
[18:36] <+SiberianSTAR> Another important bitwise logic instruction is left/right SHIFT
[18:37] <+SiberianSTAR> if you shift a number left you will multiply the number by 2
[18:37] <+SiberianSTAR> If you shift a number right you will divide a number by 2
[18:37] <+SiberianSTAR> Shift instructions are very fast
[18:38] <+SiberianSTAR> So if you have to divide a number by two you may use the shift instead of the slower division
[18:38] <+FreePlay> it's integer division, of course
[18:38] <+SiberianSTAR> yes
[18:39] <@harleyg> so in binary you have 2... 10, moving to the right is 1, 1
[18:39] <@harleyg> which in c is >> right?
[18:39] <+SiberianSTAR> >> is the right shift and corresponds to a division by two
[18:39] <+SiberianSTAR> So if in C you do A = 10 >> 1, A = 5
[18:40] <@harleyg> yes
[18:40] <+SiberianSTAR> and << is the multiplication
[18:40] <+SiberianSTAR> ok
[18:40] <+SiberianSTAR> In ASM you don't have variables
[18:41] <+SiberianSTAR> But you will have to operate directly to the registers of the CPU or on the memory
[18:42] <+SiberianSTAR> The memory is divided by text segment (code of the program), data segment (where you store your static data) and stack segment
[18:43] <+SiberianSTAR> The C compilers uses the stack segment to store your local variables of the functions
[18:44] <+SiberianSTAR> A register is a part of the CPU that can contain a value, each register of the psp is 32bits length
[18:44] <+SiberianSTAR> there are 32 Registers of general purposes and 32 floating point registers
[18:44] <+SiberianSTAR> The general purposes registers are named $0 .. $31
[18:45] <+SiberianSTAR> those registers have a mnemonic name,
[18:45] <+SiberianSTAR> $0 is also $zero and usually contains 0x00000000
[18:45] <+SiberianSTAR> $1 is a temporary register of the assembler
[18:45] <+FreePlay> "usually"?
[18:46] <+SiberianSTAR> well if you don't change that it will contains always 0
[18:46] <+SiberianSTAR>

[18:46] <+SiberianSTAR> $2 and $3 are $v0 and $v1, and are used to store the return value of the functions
[18:47] <+SiberianSTAR> (in intel 286+ cpus was used EAX to store the return value of a function)
[18:47] <+SiberianSTAR> $4, $5, $6, $7 are used to pass the arguments to a function
[18:48] <+SiberianSTAR> $28, $gp is named global pointer
[18:48] <+SiberianSTAR> $29, $sp is the stack pointer
[18:48] <@harleyg> $80$27?
[18:48] <@harleyg> $8-$27?
[18:49] <+SiberianSTAR> the stack pointer register contains the address of the first free stack byte from the top
[18:49] <+SiberianSTAR> $26 and $27 are used from the operating system
[18:50] <+SiberianSTAR> $24, $25 are for general use
[18:50] <+SiberianSTAR> $8 and $15 are for general use and are not preserved on a function call
[18:51] <+SiberianSTAR> $16 and $23 are for general use and are preserved on a function call
[18:51] <+SiberianSTAR> $30 is the frame pointer and $31 is the return address, it automatically set after a JAL instruction
[18:52] <+SiberianSTAR> ok so start with the asm instructions
[18:54] <+SiberianSTAR> The arithmetic and bitwise instructions can operate only on the registers
[18:54] <+SiberianSTAR> if you want to do a multiplication of a value stored in memory you have first to load it on a register
[18:55] <+SiberianSTAR> You can load values into registers only if the address is 4byte aligned, this means that the address is a multiple of four
[18:56] <+SiberianSTAR> the LW instruction loads a value from the memory into a register
[18:56] <@harleyg> how couldnt it be a multiple of 4?
[18:56] <+SiberianSTAR> ??
[18:56] <@harleyg> You can load values into registers only if the address is 4byte aligned, this means that the address is
[18:56] <@harleyg> a multiple of four
[18:56] <+SiberianSTAR> yes
[18:56] <+SiberianSTAR> for example
[18:56] <+SiberianSTAR> 0x00000000
[18:56] <+SiberianSTAR> 0x00000004
[18:57] <+SiberianSTAR> 0x00000008
[18:57] <+SiberianSTAR> and so on
[18:57] <+SiberianSTAR> the instruction to load a value from memory to a register is LW
[18:57] <+SiberianSTAR> the general syntax of an instruction is
[18:58] <+SiberianSTAR> mnemonic destination, source
[18:58] <+SiberianSTAR> so for example
[18:59] <+SiberianSTAR> to load the 32bits value in the position 0x00000000 of the memory in $t0
[18:59] <+SiberianSTAR> you can do
[18:59] <+SiberianSTAR> lw $t0, 0
[19:00] <+SiberianSTAR> the store instruction SW copy a value from a register into memory
[19:00] <+SiberianSTAR> sw $t0, 0
[19:00] <+SiberianSTAR> will save $t0 in the position 0 of the memory
[19:00] <+SiberianSTAR> you may set a base offset into a register, for example $t1 = 0x0000A0000
[19:01] <+SiberianSTAR> and then use that register as base offset
[19:01] <+SiberianSTAR> doing
[19:01] <+SiberianSTAR> lw $t0, 0x10($t1)
[19:01] <+SiberianSTAR> you will load into $t0 the value in the memory position 0x10 + $t1
[19:02] <+SiberianSTAR> If you see an assembly file generated by the psp-gcc compiler
[19:02] <+SiberianSTAR> you will see often the LUI instruction
[19:02] <+SiberianSTAR> with syntax is
[19:02] <+SiberianSTAR> LUI dest_register, immediate
[19:03] <+SiberianSTAR> dest_register = immediate * 0x10000
[19:04] <+SiberianSTAR> so for example
[19:05] <+SiberianSTAR> if you want to set in $2 the base offset 0x89000000
[19:05] <+SiberianSTAR> you do
[19:05] <+SiberianSTAR> LUI $2, 0x8900
[19:05] <+SiberianSTAR> and then you can use $2 as an base offset register
[19:06] <+SiberianSTAR> let see an example program
[19:08] <+SiberianSTAR>
http://rafb.net/paste/results/IHjZ3163.html[19:10] <@harleyg> ok
[19:10] <+SiberianSTAR> you can try to generate your asm code of an your c source doing psp-gcc -S code.c
[19:10] <+SiberianSTAR> let's see the asm generated by a simple C program
[19:11] <+SiberianSTAR>
http://rafb.net/paste/results/f4vwze96.html[19:11] <+SiberianSTAR> the asm generated code is
[19:11] <+SiberianSTAR>
http://rafb.net/paste/results/q7sNRo73.html[19:12] <+SiberianSTAR> you can see how for each function is used a label
[19:12] <+SiberianSTAR> the code of "function" is very simple
[19:12] <@harleyg> can you explain ?
[19:12] <+SiberianSTAR> as the first operation it sets the stack pointer
[19:13] <+SiberianSTAR> each function has to set his stack pointer
[19:13] <+SiberianSTAR> you see
[19:13] <+SiberianSTAR> addiu $sp,$sp,-16
[19:13] <+SiberianSTAR> addiu $sp,$sp,-16
[19:13] <@harleyg> yes
[19:13] <+SiberianSTAR> this puts in $sp, $sp - 16
[19:13] <+SiberianSTAR> why this ?
[19:14] <@harleyg> $sp = $sp + -16?
[19:14] <@harleyg> or is that addu
[19:14] <+SiberianSTAR> yes
[19:14] <+SiberianSTAR> but
[19:14] <+SiberianSTAR> each variable declared on your c source code takes 4 byte
[19:14] <+SiberianSTAR> some generated code is unuseful
[19:15] <+SiberianSTAR> like
[19:16] <+SiberianSTAR> moment, before i explain
[19:16] <@harleyg> ok
[19:16] <+SiberianSTAR> why it does $sp - 16 ?
[19:16] <@harleyg> huh?
[19:17] <+SiberianSTAR> bcz that function uses the first 16bytes free of the stack to store his variables and temporary data
[19:17] <+SiberianSTAR> for the first thing he sets his frame pointer
[19:17] <@harleyg> isnt it $sp = -16?
[19:17] <+SiberianSTAR> yes
[19:17] <+SiberianSTAR> the stack is LIFO style
[19:17] <@harleyg> wouldnt it be subiu if it was $sp - 16?
[19:17] <+SiberianSTAR> nono
[19:17] <+SiberianSTAR> it does
[19:18] <+SiberianSTAR> $sp = $sp - 16
[19:18] <@harleyg> isnt it add thougjh?
[19:18] <+SiberianSTAR> well if you have studied math you know that adding a negative value on a positive is equal to subtract
[19:19] <+SiberianSTAR> function(int a, int b)
[19:19] <+SiberianSTAR> and 4bytes to store the original stack pointer
[19:19] <+SiberianSTAR> - frame pointer - sorry
[19:19] <@harleyg> ok
[19:20] <+SiberianSTAR> frame pointer is used as a base-offset for variables
[19:20] <+SiberianSTAR> sw $fp,8($sp)
[19:20] <+SiberianSTAR> move $fp,$sp
[19:20] <+SiberianSTAR> in the first instruction it saves the original frame pointer in 8 + $sp
[19:20] <+SiberianSTAR> then it moves on the $fp the value of $sp
[19:21] <+SiberianSTAR> and because we compiled the code with no optimization
[19:21] <+SiberianSTAR> the generated code is stupid
[19:21] <+SiberianSTAR> sw $4,0($fp)
[19:21] <+SiberianSTAR> sw $5,4($fp)
[19:21] <+SiberianSTAR> lw $3,0($fp)
[19:21] <+SiberianSTAR> lw $2,4($fp)
[19:21] <+SiberianSTAR> in the first two instructions
[19:21] <+SiberianSTAR> the value of the variables a and b are stored into $4 and $5
[19:21] <+SiberianSTAR> ehm
[19:21] <@harleyg> ok
[19:21] <+SiberianSTAR> the value of the variables a and b are stored from the registers $4 and $5 into memory
[19:21] <+SiberianSTAR> 0 + $fp
[19:21] <+SiberianSTAR> and
[19:21] <+SiberianSTAR> 4 + $fp
[19:22] <+SiberianSTAR> (each variables is 4byte length)
[19:22] <+SiberianSTAR> then it reload the contents from the memory into the registers $3 and $2
[19:22] <@harleyg> ok
[19:22] <+SiberianSTAR> so
[19:22] <+SiberianSTAR> $3 = $4 and $2 = $5
[19:22] <+SiberianSTAR> in the next instruction it performs the addition
[19:22] <+SiberianSTAR> addu $2,$3,$2
[19:23] <+SiberianSTAR> it saves in the register $2 the result of $3+$2
[19:23] <@harleyg> $2 = $3 + $2
[19:23] <+SiberianSTAR> exactly
[19:23] <@harleyg> yeah
[19:24] <+SiberianSTAR> the register $2 is used from the gcc compiler to return the value of a function
[19:24] <+SiberianSTAR> then it restores the stack pointer and the frame pointer
[19:24] <+SiberianSTAR> the register $2 is used from the gcc compiler to return the value of a function
[19:24] <+SiberianSTAR> then it restores the stack pointer and the frame pointer
[19:24] <+SiberianSTAR> lw $fp,8($sp)
[19:24] <+SiberianSTAR> addiu $sp,$sp,16
[19:25] <+SiberianSTAR> and jumps into the address contained into the register $31
[19:25] <+SiberianSTAR> the main function is simpler
[19:25] <+SiberianSTAR> more simple
[19:25] <+SiberianSTAR> addiu $sp,$sp,-16
[19:25] <+SiberianSTAR> sw $31,12($sp)
[19:25] <+SiberianSTAR> sw $fp,8($sp)
[19:25] <+SiberianSTAR> move $fp,$sp
[19:25] <+SiberianSTAR> li $4,10 # 0xa
[19:25] <+SiberianSTAR> li $5,20 # 0x14
[19:25] <+SiberianSTAR> jal function
[19:25] <+SiberianSTAR> nop
[19:25] <+SiberianSTAR> for each function the stack-pointer and the frame pointer is set up
[19:26] <+SiberianSTAR> <SiberianSTAR> li $4,10 # 0xa
[19:26] <+SiberianSTAR> <SiberianSTAR> li $5,20 # 0x14
[19:26] <+SiberianSTAR> with these two instructions it loads on the registers $4 and $5 the value of the function call function(10, 20)
[19:26] <@harleyg> hmm
[19:26] <@harleyg> 10 = $4?
[19:26] <+SiberianSTAR> yes
[19:26] <@harleyg> ok
[19:26] <+SiberianSTAR> you know

[19:26] <@harleyg>

[19:26] <+SiberianSTAR> $4 = 10
[19:27] <+SiberianSTAR> $5 = 20
[19:27] <+SiberianSTAR> registers $4-$7 are used to send the arguments to the functions
[19:27] <+SiberianSTAR> then it calls the 'function'
[19:28] <+SiberianSTAR> JAL jump at the address specified and saves the return address into the register $31
[19:28] <@harleyg> $4 - $7 yeah?
[19:28] <+SiberianSTAR> uh?
[19:28] <@harleyg> what if the function requires... 10 arguements
[19:28] <@harleyg> hwo cn you use $4 and $7 ?

[19:28] <+SiberianSTAR> we try and we see what it does

[19:30] <+SiberianSTAR>
http://rafb.net/paste/results/sXt4CF33.html[19:30] <+SiberianSTAR>
http://rafb.net/paste/results/FMRk1r73.html[19:31] <+SiberianSTAR> it goes over
[19:31] <+SiberianSTAR> li $8,50 # 0x32
[19:31] <+SiberianSTAR> li $9,60 # 0x3c
[19:31] <+SiberianSTAR> li $10,70 # 0x46
[19:31] <+SiberianSTAR> li $11,80 # 0x50
[19:31] <+SiberianSTAR> and use the next registers
[19:31] <+SiberianSTAR> that are general-purpose registers