What is the instruction length for Register Direct addressing modes? - cpu-registers

My question is What is the instruction length for Register Direct addressing modes?
Thank you

Unclear what are you asking, but for x86, instructions are variable length.
push eax is a 1 byte.
mov eax, ebx is 2 bytes.
mov ax, bx is 3 bytes
movaps xmm0, xmm1 is 3 bytes.
All 4 above instructions directly address these registers.

Related

What differs the bp and si when memory addressing in assembly (emu8086)?

I'm using emu8086 microprocessor emulator
I wonder why when I try to place a value inside a memory address with SI it places right in DS:SI but when I try to place it with BP it goes to DS:BP+20h
here's with SI
and here's with BP
I'm sure it's something with SI being 8 bits and BP 16 bits but I don't know why it goes like that
Your program has a DATA section containing a single 17 byte string. This DATA section is followed immediately by the STACK section. Sections get paragraph aligned (16 bytes), so the DATA section is extended to have 32 bytes. This corresponds to 2 paragraphs and that is the difference that you see when looking at the values for DS and SS that mark the start of those sections:
DS=0710h
SS=0712h
An instruction that uses [si] addresses the DS segment, and an instruction that uses [bp] addresses the SS segment.
Because there's a difference of 32 bytes between these sections, you can address the first byte of the STACK section normally through mov al, [bp] (BP=0) but also via mov al, [0020h] or mov al, [ds:bp+32].
I'm sure it's something with SI being 8 bits and BP 16 bits
SI is a 16-bit register.
The 8-bit registers are AL, AH, BL, BH, CL, CH, DL, and DH.
The 16-bit registers are AX, BX, CX, DX, SI, DI, BP, SP, CS, DS, ES, and SS.

Why does CMP L and CMP M instructions in Microprocessor 8085 have same opcode BD?

CMP L compares Accumulator(A) contents with L register. CMP M compares Accumulator(A) contents with 8-bit data stored in the memory location as stored in H-L register pair. That's two different operations totally so why is there the same opcode BD for them both.
PS: Yeah I know that few Instructions have same opcode if they perform about the same task and have different names for referring to the same task. But what is it in this case?

executing SPI command in function in under 1ms - 8051

Currently I have an AT89C2051 microcontroller hooked up to an ISD soundchip through a multiplexer-demultiplexer setup. I have other things too but my focus is making sound execute as fast as possible. Currently the speed of the chip is 3.6Mhz since another microcontroller is driving this microcontroller.
Based on documentation and experimentation, The sound chip requires 7 bytes to be sent to it in order for me to make it play sound between any two ranges of memory. The part that takes the time is transmitting the seven bytes.
This is the code I have so far that works:
FLUSH bit P3.7 ;Low=enable data reception
ENXMIT bit P3.5 ;High=Enable data transmission
GLOBALCLK bit P3.1 ;TXD: clock (connects to soundcard clock)
GLOBALDAT bit P3.0 ;RXD: I/O data line (connects to MISO and MOSI)
C_SND2 = address of soundcard 2
C_SND = address of soundcard 1
O_SND:
setb FLUSH ;disable reception
clr ENXMIT ;disable transmission
mov R7,A ;Parameter in: Accumulator = # bytes to transfer out.
mov A,#C_SND2 ;A=address of soundcard 2
mov R6,#C_SND ;R6=address of soundcard 1
jnb SS,nc1 ;Parameter in: SS = soundcard to use.
xch A,R6 ;Switch A + R6 if other soundcard is wanted.
nc1:
;NOTE: soundcard Slave select lines are connected together through an inverter.
mov P1,R6 ;Enable wrong soundcard (to disable the correct one)
mov R0,#BUFOUT ;Set data space pointer
mov P1,A ;Now enable only the correct soundcard
setb ENXMIT ;Enable data transmission
tx2:
mov A,#R0 ;Load a byte from our data space
;This fragment executes 8x but I only showed it one time here.
;I avoided loops. DJNZ requires two clock cycles (7uS) to process command.
clr FLUSH ;Enable data input **
setb GLOBALDAT ;Set data to high impedance so input can be captured **
clr GLOBALCLK ;Lower clock line to accept bit input **
mov C,GLOBALDAT ;Get incoming bit
setb FLUSH ;Disable data input
rrc A ;store incoming bit and load next output bit
mov GLOBALDAT,C ;set data line to bit
setb GLOBALCLK ;raise clock so soundcard accepts bit
;end of repeating fragment
mov #R0,A ;save what soundcard sent us to our data space
inc R0 ;increment pointer
djnz R7,tx2 ;Keep going until all bytes are processed
clr ENXMIT ;Disable further transmissions
setb GLOBALDAT ;Set data line to high
mov P1,R6 ;reset the SS line to tell soundcard we're done.
;Save audio statuses to RAM
mov AUDSTATL,BUFOUT
mov AUDSTAT,BUFOUT+2
ret
As you can see, the data line (RXD) from the microcontroller is shared across every data line in the system through multiplexers/demultiplexers. This means that I need to make the line only unidirectional (not bi-directional) by enabling reception and transmitting nothing when I want to receive data.
I called the receive enable "FLUSH" because it also flushes other output lines which are out of the scope of this question.
Now what I want to try to do is make this code fragment execute much faster.
So I'm looking at these lines:
clr FLUSH ;Enable data input **
setb GLOBALDAT ;Set data to high impedance so input can be captured **
clr GLOBALCLK ;Lower clock line to accept bit input **
and thought instead of consecutive clear and setb statements on individual pins on the same port, I could use ANL or ORL but then if I did it direct on the port, the result might not update correctly due to the behaviour of the 8051.
Is there any other way I can modify the repetitive code to make the thing run faster?
I already did save at least 380 microseconds (6.5 microseconds per removal of DJNZ multiplied by the usage of it 8 times for a byte + 1 to load counter variable for DJNZ + other commands in loop then multiplied by bytes to process command (7 bytes))
But I want to save more than that.
Any ideas?
Except that I don't plan to remove the outer loop because doing that will increase the need for rom space substantially more and I don't have too much free rom space left.
It is possible to use two different port pins for FLUSH and ENXMIT. By doing so, you can go for ANL or ORL on the port directly.

how to use Base Pointer in Assembly 8086 to go through the stack?

I have an assigment in which I have to insert two digit integers into the stack. Search a number in the stack and return in which position this number is, print all the numbers in the stack and delete a number from the stack.
Right now I'm trying to print all the numbers in the stack by going through the stack using the base pointer, but my code doesn't work.
mov di,offset bp
mov ax, [di] ;trying to move de value stored in di direction in stack to Ax
mov digito,ah
mov digito2,al
mov dl,digito
mov ah,02
int 21h
mov dl,digito2
mov ah,02
int 21h
mov ah,01
int 21h
So in this code I'm trying to print the two number digit by getting the bp into di (so later I can decrement it to go through all the stack), and the passing the number stored in that direction in Ax. I'm a newby in assembly so I don't know what I'm doing.
Thank you in advance for your time. (And sorry for my english)
Sorry for the delayed reply. First, bp doesn't really have an "offset", so you could remove that. Second, bp won't automatically point into the stack unless you have made it so (mov bp, sp).
You don't mention an OS, but int 21h identifies it as DOS... which is real mode, segmented memory model. mov ax, [di] defaults to mov ax, ds:[di]. If you've assembled this into a ".com" file, cs, ds, es, and ss are all the same. If you've assembled it into an ".exe" file, this is not so! You may want to write it as mov ax, ss:[di] to be sure. In contrast, mov ax, [bp] defaults to mov ax, ss:[bp], so you may want to use bp instead of di here. I suspect that's how you're "supposed" to do it. If you've got a ".com" file, you can forget about this part (in 32-bit code you can forget about it too, but that doesn't apply to you).
Then... your attempt to print a number isn't really going to work properly. Look for "How do I print a number?" examples for more information on that - too much to get into here...
This is too hard an assignment for a beginner, IMO (but "the instructor is always right" :) ).

Pointers and Indexes in Intel 8086 Assembly

I have a pointer to an array, DI.
Is it possible to go to the value pointed to by both DI and another pointer?
e.g:
mov bl,1
mov bh,10
inc [di+bl]
inc [di+bh]
And, on a related note, is there a single line opcode to swap the values of two registers? (In my case, BX and BP?)
For 16-bit programs, the only supported addressing forms are:
[BX+SI]
[BX+DI]
[BP+SI]
[BP+DI]
[SI]
[DI]
[BP]
[BX]
Each of these may include either an 8- or 16-bit constant displacement.
(Source: Intel Developer's Manual volume 2A, page 38)
The problem with the example provided is that bl and bh are eight-bit registers and cannot be used as the base pointer. However, if you set bx to the desired value then inc [di+bx] (with a suitable size specifier for the pointer) is valid.
As for swapping "the high and low bits of a register," J-16 SDiZ's suggestion of ror bx, 8 is fine for exchanging bl and bh (and IIRC, it is the optimal way to do so). However, if you want to exchange bit 0 of (say) bl with bit 7 of bl, you'll need more logic than that.
DI is not a pointer, it is an index.
You can you ROR BX, 8 to rotate a lower/higher byte of a register.

Resources