Base + Offset Addressing Mode - addressing-mode

I just need an explanation of how base + offset addressing modes work. Having trouble finding a clear-cut answer for this. (I've been working with the LC-3, not sure if that matters). A simple example would also be helpful.
Thank you!

MOV EAX,[EBP+8]
MOV EBX,[EBP+12]
EBP is the base here (holds the base address) like "00402000" for instance
so the EAX will be loaded with the value in the address [00402000+8] I.e 00402004

Base + Index addressing mode
2 Registers specify the address of an operand in an instruction.
Add the numerical values stored in those registers to get the complete address of an operand.
Ex.
A = 1000
Register A = 1000
Register B = 8
MOV C, [A,B] => C = contents of location A+B
There is a flavor to Base + Indexing addressing called the base + Index + displacement
Displacement = immediate value in the instruction that is added to the Base + Index.
thats what you see in your opcode.
instruction = OPCODE + Operand 1 Register Spec + Operand 2's Base Register Spec + Operand 2's Index Register Spec + Immediate value.
imagine a microprocessor with a 8 bit register space.
so a 16 bit operand may have
4 bit for opcode
3 bit for base register
3 bit for index register
6 bit for immediate displacement.
Thanks,

I believe I have figured out the answer. I'll post it here in case it helps anyone else who has trouble with this. I found the answer hidden deep in the 100 slide powerpoint that my teacher provided XD
This is what happens when performing an LDR using a base register R6 and destination register R2:
MAR<-R6 + IR[5:0]
MDR<-MEM[MAR]
R2<-MDR
Lets say R6 = x3000, IR[5:0] = x5, and R2 = 0 (although this value doesn't matter since it will be loaded with another value at the end)
MAR<-R6 + IR[5:0]
R6 is added to IR[5:0] (which is the offset value in the last six bits of the LDR instruction). The base x3000 (value of R6) has x5 (value of IR[5:0]) added to it, giving us x3005. The MAR (memory address register) now holds x3005.
MDR<-MEM[MAR]
The value in the MAR (x3005) is loaded into the MDR (memory data register).
R2<-MDR
The value in the MDR (x3005) is loaded into R2. R2 now holds the value: x3005.
I hope this question helps those new to addressing modes like I am :)
Thank you all.

Related

Why is 38 written as 9 + 9 + 9 +12 - 1 in xv6 RISC-V source code

I was trying to add a few system calls to the xv6 source code developed at MIT, and upon reading this resource (https://pdos.csail.mit.edu/6.S081/2020/xv6/book-riscv-rev1.pdf), on page 26, they consider the maximum possible virtual address that XV6RISC-V supports.
When I tried to look at the source code for the definition of MAXVA (MAXimum Virtual Address), I came across the following code snippet.
// one beyond the highest possible virtual address.
// MAXVA is actually one bit less than the max allowed by
// Sv39, to avoid having to sign-extend virtual addresses
// that have the high bit set.
#define MAXVA (1L << (9 + 9 + 9 + 12 - 1))
I was intrigued by the expression '9 + 9 + 9 + 12 - 1' instead of simply writing '38'. I tried to look up the underlying reasoning for this but did not find anything related. Is this some kind of optimization? If so, at what level is this relevant and where else could this be relevant?
I have some experience in assembly language programming and understand the basics of how the C code written is being translated to the assembly structure and how the final assembly code corresponding to bit shifting might look like, (using x86 salq and sarq or RISC-V slli). Any hints/ thoughts would be appreciated as well.
The answer could be guessed from vm.c
// The risc-v Sv39 scheme has three levels of page-table
// pages. A page-table page contains 512 64-bit PTEs.
// A 64-bit virtual address is split into five fields:
// 39..63 -- must be zero.
// 30..38 -- 9 bits of level-2 index.
// 21..29 -- 9 bits of level-1 index.
// 12..20 -- 9 bits of level-0 index.
// 0..11 -- 12 bits of byte offset within the page.
9+9+9 correspond to each 9 bits index to address the page
12 correspond to the offset in the page
For the compiler, write 9+9+9+12-1 is the same than 38, but for the human -aware of bits fields- reading this, the first is more clear.

ModBus to Click PLC

Looking for help with understanding how to change value in address DS1 (400001). First the click appears to use a 6 digit Modbus so not sure how to deal with the in 2 bytes. I think I read 40001 is the same but do not see how. I am able to receive data and understand the data when the Click PLC is the master. I would like my PC to be the master and change the address.
Here is the data I am sending to the PLC. I am expecting this data to be sent to PLC slave 02 and change the data in DS1 (400001) to the value of zero.
frame(0) = 2 'Slave Address =2
frame(1) = 6 'Mode =6
frame(2) = CByte(40001 / 256) '
frame(3) = CByte(40001 Mod 256) '
frame(4) = 0 '
frame(5) = 0 '
Dim crc As Byte() = CRC(frame) ' Call CRC Calculate.
frame(6) = crc(0) '=59 Error Check Lo
frame(7) = crc(1) '=189 Error Check Hi
SerialPort1.Write(frame, 0, frame.Length)
Realize that Application Layer addressing in Modbus is different than the bytes on the wire. The leading digit in an application layer address (e.g. 4xxxx for Holding Register) is implied in the function code (e.g. Read Holding Register)
So on the wire, you drop the leading 4, and left with an offset of 1-65536 (yes, Application Layer offsets are 1-based). But on the WIRE, they are 0-based, so you then subtact 1 from the offset to get the value 0-65535.
So, sometimes you see Application Modbus HRs like 4001, 40001, or 400001, all referencing the first HR in the device. 5 digit is most common. I do see 4 digit for old RTU devices. I do see a 6 digit every once in a while where the remote device has a ton of memory (or not, like Click).
Realize that a lot of devices are implemented by people who only understand the low level protocol, so when they say something is at address 40001, it may actually be at offset 0x0001, or 0x0000 (the correct offset on the wire). I even saw one implementation that implemented the address 40001 as literally 0x9C41 on the wire (maybe 0x9C40). Yes, 6 digit Application Layer Holding Register 440001.

What control lines are asserted/set to 1 when a load double word instruction is called?

Using this diagram, I am looking at this instruction to determine what control lines are necessary.
ld x5, 40(x9)
x5 = 0x000000ff
x9 = 0x00000fff
I am curious what control lines (RegWrite, MemRead, MemWrite, MemtoReg, Branch, Zero, ALUSrc) are asserted or set to 1 in order for this instruction to run, and why I understand the parts of the load double instruction to be ld RT, Disp(RA) - but what is required for execution and why? Thank you - resources on these things (that make sense to me) are extremely limited on the internet.
Its a LOAD instruction in which the memory address to be read is calculated by adding 40 to the contents of the register x9, the result is then stored in register x5.
Instruction is writing to registers, therefore assert RegDst and RegWrite
Instruction is required to add 40 to the contents of x5. Set ALUSrc to 1 to select 40 as one of the source.
Assert MemReadas its a memory read. Also set MemtoReg to 1 so that mux will get the data from Memory rather than ALU.

interpreting i2c register map for ISL12022

I am trying to program an ISL12022M RTC and am having trouble interpreting the register map (self taught with little experience). The documentation says that the RTC registers (SC,MN,HR,DT,MO,YR,DW) are BCD representations. In order to allow write capabilitiy into the RTC registers the WRTC bit(bit 6 of address 08h is set to '1'.The map looks like this:
The FAQ example from the Intersil site tells me that to set the WRTC bit I need to send DEh (slave address) 08h (register address) and 41 (Enable WRTC bit, other bits remain in default). Why not hex? Why 41 and not 40? And what does SC22 in SC bit 6, SC21 in bit 5, etc. mean?
Datasheet
Example
I've read the documentation until I can't see anymore and I've searched until I am just getting more confused. Any help is appreciated.
Well, it looks like these values in the map are nibbles. The range for the first register is 0 - 59. When represented in BCD, 4 bits are needed for the digit in the ones place and three bits are needed for the 10's place. So, bits 0 - 3 belong to the first nibble; bit 0 = SC(register name)1(first nibble)0(first bit). Bits 4, 5 and 6 belong to the second nibble. Bit 4 = SC(register name)2(second nibble)0(first bit). Bit 7 is not needed.
The example sheet from Intersil has a typo; the WRTC value needs to be 40h or 41h.

How to generate 0xE8 (call) opcode with C++

Basically, what I have is a game which has a function MyFunc(), and it's called on 4 places in the game. One of the addresses is 0x10002000, and the bytes are E8 0B 83 01 00.
I'm injecting a DLL, and want to patch that 0xE8 (call) to my own address. When I do it with Cheat Engine's Auto Assembler and write call MYADDRESS, it generates the proper opcode, and proper bytes.
However, if I do it with the DLL, this is what I get:
What I want to achieve is call 74C611CC. So I need to generate the bytes for the opcode to be like I want instead of what is it currently (in the screenshot)
I use this kind of code:
*(BYTE*) dwPatchAddr = 0xE8;
*(DWORD*) (dwPatchAddr + 1) = (DWORD) myFunc;
An e8 instruction is a relative call instruction, not absolute. So the next 4 bytes need to be the difference between the pc when processing this instruction and your target function. So what you want is:
*(BYTE *)dwPatchAddr = 0xE8;
*(DWORD *)(dwPatchAddr + 1) = (DWORD)((char *)myFunc - (char *)(dwPatchAddr + 5));
Note that the PC address used to compute the offset is actually the address of the next instruction after the call (what will also be pushed as the return address).