MIPS basic store (at address zero?) - mips32

So far I've written one assembly program that didn't use data memory at all. Now I'm trying to write a super simple program that stores a value then loads that value into a different register (and prints things to make sure I'm sane).
li $t0, 13 # data that I want to store
li $v0, 1
move $a0, $t0
syscall
sw $t0, 0($zero) # error
#lw $t1, 32
#li $v0, 1
#move $a0, $t1
#syscall
I keep getting an 'address out of range' error. I've tried changing the offset to different values (4, 8, 32) and even tried loading immediates into a register so I'm not using the $zero register.
What do I use as a base address if all my program has is data? What is wrong with storing a data value at address zero? My textbook/brain lead me to believe that this was absolutely fine..

That's because there is no memory mapped to address 0. It is most likely somewhere after 0x10000000, (usually 0x10010000 in MARS) in which you will see when you look at the data segment window of the simulator.
So, if you want to access a word at the beginning of the data segment, put a label
ie:
.data
startofdata: .word 0
and in the code section:
la $a0, startofdata
sw $t0, 0($a0)
startdata could be named error, if you wanted to label each location to make it more readable

Related

Encoding basic instruction formats in MIPS

I'd like to figure out how to encode BASIC INSTRUCTION FORMATS referred to in the MIPS Green Sheet
e.g. I'd like to encode the instruction add $t0 $t1, $t2.
I know that the Format is R; opcode will be 0x0; The Funct 0x20.
But how will I get the code for rs, rt, rd and shamt?
The link in the question is mangled. It should be https://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdf
If you look in the REGISTER NAME, NUMBER, USE, CALL CONVENTION box at the bottom right of page 1 of that PDF, you'll see that the registers with names $t0 through $t7 correspond to the registers numbered 8 through 15. For the instruction you're interested in:
add $t0, $t1, $t2
$t0 is the destination register, specified by the rd field in the instruction. Since $t0 is register number 8, put 01000 into the rd field.
$t1 and $t2 are the source registers, specified by the rs and rt fields in the instruction. Since $t1 is register number 9 and $t2 is register number 10, put 01001 into the rs field and put 01010 into the rt field.
shamt is not used in the add instruction, so fill that field with zeroes.
BTW, that Green Sheet is fine as a reminder of the nitty-gritty details of the instruction set, but something like https://www.cs.ucsb.edu/~franklin/64/lectures/mipsassemblytutorial.pdf will be more helpful if you're just getting started with the MIPS architecture.

Reverse Engineering: changing AL register without overwriting instructions

I am trying to learn more about reverse engineering by debugging and patching a 64 bit windows executable. I am using x64dbg (Much like ollydbg but with 64 bit support)
I have some assembly that looks roughly like this:
call test_exe.44AA9EB20
mov byte ptr ds:[44AB9DA15], al
[More instructions...]
[More instructions...]
[More instructions...]
the function call in the first line sets the rax register to have a value of 0. Therefore, the second line is moves a value of 0 into the pointer at 44AB9DA15.
I want to reassemble some code so that a value of 1 gets put into this pointer.
I can do something like this:
call test_exe.44AA9EB20
mov byte ptr ds:[44AB9DA15], 1
However, since al is only an 8 bit register, assembling the code to the above seems to run over some of the subsequent instructions.
I know that I can solve this problem by stepping into the function call test_exe.44AA9EB20 and setting rax to have a value of 1 before the ret instruction, but I am curious if there is an easier way.
Is there some way I can give this pointer (44AB9DA15) a value of 1 without running over subsequent instructions?
You want to replace MOV [0x000000044AB9DA15],AL which is encoded as 88042515DAB94A (7 bytes)
with MOV BYTE PTR [0x000000044AB9DA15],1 which is encoded as C6042515DAB94A01 (one byte longer).
Try to use RIP-relative encoding. First calculate the difference between the target pointer and the offset
of following instruction ($+instruction_size). If it is less than 2GB, for instance 0x11223344,
the encoding of MOV BYTE PTR REL [0x000000044AB9DA15-$-7] will be C6054433221101 (exactly 7 bytes).
Or, if test_exe doesn't have to be called, overwrite the CALL instruction with code which sets AL to 1,
e.g. MOV AL,1, and pad the remaining four bytes with NOP.

PIC30F Data EEPROM reads 0xFFFF first time around

The first time my PIC30F code reads a word from Data EEPROM, it reads 0xFFFF instead of the data actually in EEPROM. It reads fine afterward.
After a bad read, I checked W1 and it does have the correct address
There are no words in data EEPROM with a value of 0xFFFF
I checked the supply: it's 5.13 V
If I break right before the table read instruction, and step through it, it woks fine
I know that NVMADRU and NVMADR are not involved in reading, but I checked them, and their value doesn't change between good reads and bad reads
It's a dsPIC30F5011
I checked the Errata, and did not find any reference to such issue
I am working through the debug function of MPLAB 8, with a PICkit II
I am working through the debug function of MPLAB 8, with a PICkit II: I reset, then run, and it fails
If I place the code in a tight loop until the value is correct, and counting the number of iterations, I see that it takes 2339 times through the loop until it reads correctly
EEPROM read code:
_ReadEEWord:
;--------------------------------------------------------------------------------
; Read a word from Data EEPROM
; Entry W0 Word address relative to the start of Data EEPROM
; Exit W0 Word at that location
; Uses W1, Table pointer
;--------------------------------------------------------------------------------
; Start address of Data EEPROM
#define DATAEE_START 0x7FFC00
; Setup pointer to EEPROM memory
mov #0x7F,W1 ; Set the table pointer
mov W1,TBLPAG ; to the page with the EEPROM
add W0,W0,W0 ; Convert the word address to a byte address
mov #0xFC00,W1 ; Add the start of EEPROM
add W1,W0,W1 ; to the address
nop
nop
nop
; Return the EEPROM data
tblrdl [W1],W0 ; Read the EEPROM data
nop
nop
nop
return
Any suggestions of what may be causing that?
SOLVED
The documentation doesn't say so, but, before you can read data EEPROM, you must wait for any previous EEPROM operations to be done.
You can do it in one of these ways:
1) In C:
#include <libpic30.h> // Includes EEPROM utilities
_wait_eedata(); // Wait for the erase to be done
2) In C, no lib import
while (NVMCONbits.WR);
3) In assembly:
btsc NVMCON,#15 ; If busy (WR bit s set)
bra $-2 ; Go back and wait

Assemble IA-32 mov [bootdrv], dl

I just start to program IA-32 assemble and boot loader and I can't understand one command: mov [bootdrv], dl.
dl is the low 8 bits of data register, but I dont know what is [bootdrv]. Is it a variable or something? How could a register be placed in [bootdrv]?
start:
mov ax,0x7c0 ; BIOS puts us at 0:07C00h, so set DS accordinly
mov ds,ax ; Therefore, we don't have to add 07C00h to all our data
mov [bootdrv], dl ; quickly save what drive we booted from
This is the beginning 3 line of a boot loader and [bootdrv] just appear without any definition, I couldn't understand.
Any information would be helpful and appreciated, thank you!
[bootdrv] is a specification of an absolute memory address. The code:
mov [bootdrv], dl
copies the contents of the 8-bit DL register into a byte in memory, at the address resulting of multiplying the current value of DS by 16, then add the value bootdrv. bootdrv itself is a label, which a value that represents where in the current data segment is the memory position located.
On the other hand, the symbol bootdrv must be defined somewhere. Otherwise, the assembler will stop with a "symbol not defined" error. Maybe it's defined past the code (assemblers do two passes through the source code in order to get all symbols so they can be used even if they are defined after the code sequence that uses them). Maybe it's in a separate .INC file.
mov [bootdrv], dl indicates a segment:offset memory access. In the previous instruction, you configured the Data Segment register with an address, so the mov [bootdrv], dl instruction writes to the segment:offset address 0x7c0:bootdrv, whatever bootdrv might be.

How to turn off MIPS-GCC automatic instruction reordering?

Following this question: Weird MIPS assembler behavior with jump (and link) instruction I have a working GNU assembly toolchain for my single cycle MIPS project (no branch delay slot!). I would really prefer to write in C though. The code itself generated from the compiler does run, but I have to manually edit the assembly source every time since GCC for some reason likes to automatically reorder the branching instructions itself. I don't want to hack this with a script to figure out when to reorder the branches back again.
Is there a possible way to circumvent this? GCC generates code like this for some reason:
.set noreorder
...
jr $ra <-- GCC reordered for me!
addi $v0, $v0, 10 <--
...
.set reorder
where I really want to feed the assembler something like this:
.set noreorder
addi $v0, $v0, 10
jr $ra
pass the -mips1 and -fno-delayed-branch flags to gcc.
I don't think it's possible to turn it off since delay slots are present in all MIPS variants. I think it's much better if you implement delay slots in your emulator. This will also make it closer to real hardware.
Barring that, you can probably patch gcc to stop trying to fill the delay slots.

Resources