How do Stack Machines and 3AC Machines solve expressions? - stack-machine

So, I'm struggling a little on how Stack Machines & 3AC (Register) Machines interpret expressions. Take this expression for an example:
4 * 2 - 3
As a 3AC Machine (instruction sets feature three-operands, a type of Register Register Machine), I think it would look something like this
(Note - I use '#' for comments, pretty sure that this isn't the correct syntax):
LOAD 4, r0 # register 0 stores 4
LOAD 2, r1 # register 1 stores 2
MUL r0, r1, r0 # register 0 now stores 8 (4 x 2)
LOAD 3, r1 # register 1 now stores 3
SUB r0, r1, r0 # register 0 stores 5 (8 - 3)
Sorry about the formatting. I don't know how to get subscripts in code blocks.
I think a Stack Machine would look something like this:
LOAD 4
LOAD 2
MUL
LOAD 3
SUB # would this be 8 - 3 or 3 - 8?
NEG # if its 3 - 8 then I need to negate the top
PRINT # outputs the top of the stack
HALT

Related

Sorting only odd/even numbers in assembly, how to copy an array without using already allocated memory?

TL;DR: How to copy elements from one array to another (not all but some)?
I want to perform a sorting algorithm on some array, but so that I only sort odd or even numbers in it, depending on a flag. So my idea was to set a flag on either 0 or 1 and then I'd extract all the numbers that have to be sorted into another array and put -1 (as a marker) on the positions where those numbers were. After that I'd just insert the sorted numbers back into the original array, for example:
arr1: 5 8 2 4 13 9 14 10 9
arr2: 8 2 4 14 10
arr2 (sorted): 2 4 8 10 14
arr1 (without even numbers): 5 -1 -1 -1 13 9 -1 -1 9
arr1 (final): 5 2 4 8 13 9 10 14 9
Now while writing this in a higher language is rather trivial for me, doing it in assembly which I'm learning for a class isn't. The part where I sort the numbers works just fine, but the part that causes me problems is the one where I have to copy the numbers into another array. My main method looks like this:
section .data
arr dd 6,8,1,7,4,2,9,107,10,8,12,16,14,5
len equ ($-arr) / 4 - 1
section .bss
section .text
extern sort
global _start
_start:
mov r8, len
mov esi, arr ; esi points to the start of the array/top of it
call sort
mov rax, 60
mov rdi, 0
syscall
And the subroutine which will do the job (showing only the problematic part):
mov r9d, esi
.export:
mov eax, [r9d]
cdq
div dword [divider]
cmp edx, [flag]
je .add
.continue:
add r9d, 4 ; point to the next number
inc dword [i]
cmp r8d, [i]
jg .export
.add:
mov edi, [r9d]
mov dword [r9d], -1 ; put the number in the old array to -1
sub edi, 4
inc dword [lenNewArray] ; inc the total number of elements in new array
jmp .continue
Anyway what I want to accomplish is that I add an element that matches the condition to some location and then point rdi to that location, when I want to add another element I subtract -4 from rdi so it points to the lower location and put that element there, in the end I'd have rdi pointing to the last element which was extracted, is that possible to be done, and is it a bad way?

LC-3 Assembly Accessing Array Values

I was given an array, defined by:
.orig x6000
.fill -20
.fill 14
.fill 7
.fill 0
.fill -3
.fill 11
.fill 9
.fill -9
.fill 2
.fill -5
.end
I need to iterate through these values within my main program. From what I understand this "array" is just values stored in memory far away from where the instructions are stored. My question is, "How do I load these values?" I know that they start at x6000, but I don't know how to get to them using instructions.
The best thing to do would be to read the LC3 ISA and pay special attention to the LDR instruction.
Here is an example program to help get you started.
You need to know and keep track of two things: (1) the address of the array and (2) the length of the array/index as you iterate. For (1), I chose to use a filled value; for (2) the length of the array is defined in the instruction itself. I AND R1, R1, 0 to clear the register and add 10. We could just as easily have a filled value LENGTH equal to 10 and LD R1 LENGTH.
The loop begins by decrementing R1 and checking to see if it is negative. If R1 is negative, then the loop exits. We decremented length first, so you can think of the "length" (value in R1) as an index. So, if the index < 0, then the loop exits.
The LDR R0, R2, 0 instruction gets the value at the address in register R2 offset by 0 and puts it in R0. Presumably you would want to do something with the data after this line.
Before the unconditional branch to LOOP, we increment the address of the array to point at the next element.
.orig x3000
LD R2, ARRAY ; R2 = x6000
AND R1, R1, 0 ; R1 = 0 (clear before add)
ADD R1, R1, 10 ; R1 = 10 (length of array)
LOOP ADD R1, R1, -1 ; R1--
BRn DONE ; if R1 < 0 then halt, else...
LDR R0, R2, 0 ; R0 <-- mem[R2 + 0]
ADD R2, R2, 1 ; R2++
BR LOOP ; loop
DONE HALT ; halt
ARRAY .fill x6000
.orig x6000
.fill -20
.fill 14
.fill 7
.fill 0
.fill -3
.fill 11
.fill 9
.fill -9
.fill 2
.fill -5
.end

MSP430 microcontroller - how to check addressing modes

I'm programming a MSP430 in C language as a simulation of real microcontroller. I got stuck in addressing modes (https://en.wikipedia.org/wiki/TI_MSP430#MSP430_CPU), especially:
Addressing modes using R0 (PC)
Addressing modes using R2 (SR) and R3 (CG), special-case decoding
I don't understand what does mean 0(PC), 2(SR) and 3(CG). What they are?
How to check these values?
so for the source if the as bits are 01 and the source register bits are a 0 which is the pc for reference then
ADDR Symbolic. Equivalent to x(PC). The operand is in memory at address PC+x.
if the ad bit is a 1 and the destination is a 0 then also
ADDR Symbolic. Equivalent to x(PC). The operand is in memory at address PC+x.
x is going to be another word that follows this instruction so the cpu will fetch the next word, add it to the pc and that is the source
if the as bits are 11 and the source is register 0, the source is an immediate value which is in the next word after the instruction.
if the as bits are 01 and the source is a 2 which happens to be the SR register for reference then the address is x the next word after the instruction (&ADDR)
if the ad bit is a 1 and the destination register is a 2 then it is also an &ADDR
if the as bits are 10 the source bits are a 2, then the source is the constant value 4 and we dont have to burn a word in flash after the instruction for that 4.
it doesnt make sense to have a destination be a constant 4 so that isnt a real combination.
repeat for the rest of the table.
you can have both of these addressing modes at the same time
mov #0x5A80,&0x0120
generates
c000: b2 40 80 5a mov #23168, &0x0120 ;#0x5a80
c004: 20 01
which is
0x40b2 0x5a80 0x0120
0100000010110010
0100 opcode mov
0000 source
1 ad
0 b/w
11 as
0010 destination
so we have an as of 11 with source of 0 the immediate #x, an ad of 1 with a destination 2 so the destination is &ADDR. this is an important experiment because when you have 2 x values, a three word instruction basically which one goes with the source and which the destination
0x40b2 0x5a80 0x0120
so the address 0x5a80 which is the destination is the first x to follow the instruction then the source 0x0120 an immediate comes after that.
if it were just an immediate and a register then
c006: 31 40 ff 03 mov #1023, r1 ;#0x03ff
0x4031 0x03FF
0100000000110001
0100 mov
0000 source
0 ad
0 b/w
11 as
0001 dest
as of 11 and source of 0 is #immediate the X is 0x03FF in this case the word that follows. the destination is ad of 0
Register direct. The operand is the contents of Rn
where destination in this case is r1
so the first group Rn, x(Rn), #Rn and #Rn+ are the normal cases, the ones below that that you are asking about are special cases, if you get a combination that fits into a special case then you do that otherwise you do the normal case like the mov immediate to r1 example above. the destination of r1 was a normal Rn case.
As=01, Ad=1, R0 (ADDR): This is exactly the same as x(Rn), i.e., the operand is in memory at address R0+x.
This is used for data that is stored near the code that uses it, when the compiler does not know at which absolute address the code will be located, but it knows that the data is, e.g., twenty words behind the instruction.
As=11, R0 (#x): This is exactly the same as #R0+, and is used for instructions that need a word of data from the instruction stream. For example, this assembler instruction:
MOV #1234, R5
is actually encoded and implemented as:
MOV #PC+, R5
.dw 1234
After the CPU has read the MOV instruction word, PC points to the data word. When reading the first MOV operand, the CPU reads the data word, and increments PC again.
As=01, Ad=1, R2 (&ADDR): this is exactly the same as x(Rn), but the R2 register reads as zero, so what you end up with is the value of x.
Using the always-zero register allows to encode absolute addresses without needing a special addressing mode for this (just a special register).
constants -1/0/1/2/4/8: it would not make sense to use the SR and CG registers with most addressing modes, so these encodings are used to generate special values without a separate data word, to save space:
encoding: what actually happens:
MOV #SR, R5 MOV #4, R5
MOV #SR+, R5 MOV #8, R5
MOV CG, R5 MOV #0, R5
MOV x(CG), R5 MOV #1, R5 (no word for x)
MOV #CG, R5 MOV #2, R5
MOV #CG+, R5 MOV #-1, R5

Table sort and lookup

I have an excel table (25x25) which looks like this,
C1 C2 C3
R1 5 6 7
R2 1 7 9
R3 2 3 0
my goal is to make it look like this,
C3 R3 0
C1 R2 1
C1 R3 2
C2 R3 3
C1 R1 5
C2 R1 6
C2 R2 7
C3 R1 7
C3 R2 9
It generates a new table ranked by the values in the first. It also tells the corresponding column and row name.The table has duplicates, negatives and decimals.
I'm doing this because I'd like to find the 3 closest candidates (and hence the C's and R's) of a given value. And VLOOKUP() requires a sorted table.
Another problem (a step forward) is that VLOOKUP() returns the closest smaller value instead of actually the smallest. Is there a better way to do it or a workaround? So that the result is a neat table like such,
Value to look up = 2.8
>> C2 R3 3
>> C1 R3 2
>> C1 R1 5
For some reasons I cannot use VBA for this project. Any solutions with just built-in functions in MS Excel?
If you need to use only native worksheet functions, this can be accomplished; even without array formulas.
        
With your original data in A1:D4, the formulas in F3:H3 are,
=INDEX(B$1:D$1, AGGREGATE(15, 6, COLUMN($A:$C)/(B$2:D$4=H3), COUNTIF(H$3:H3, H3)))
=INDEX(A$2:A$4, AGGREGATE(15, 6, ROW($1:$3)/(B$2:D$4=H3), COUNTIF(H$3:H3, H3)))
=SMALL(B$2:D$4,ROW(1:1))
Fill down as necessary.
The formulas in K5:N5 are,
=INDEX(B$1:D$1, AGGREGATE(15, 6, COLUMN($A:$C)/(B$2:D$4=M5), COUNTIF(M$5:M5, M5)))
=INDEX(A$2:A$4, AGGREGATE(15, 6, ROW($1:$3)/(B$2:D$4=H3), COUNTIF(M$5:M5, M5)))
=IF(COUNTIF($B$2:$D$4, N5+$K$2)>=COUNTIF(N$5:N5, N5), N5+$K$2, $K$2-N5)
=AGGREGATE(15,6,ABS($B$2:$D$4-$K$2),ROW(1:1))
Fill down as necessary.
I've included enough rows in the K5:N13 matrix that you can see how the two 7 values are handled.

Setting text and background in Assembly intel

I have a programming assignment to run through and set the background and text of all the possible combinations. I am using a predefined function called SetTextColor which basically sets the values like this:
mov eax, white + (blue * 16)
Essentially this sets the text white and the background blue (to set the background you multiply by 16). Basically the combination is 16 X 16 = 256
TITLE BACKGROUND COLORS (main.asm)
; Description: T
; Author: Chad Peppers
; Revision date: June 21, 2012
INCLUDE Irvine32.inc
.data
COUNT = 16
COUNT2 = 16
LCOUNT DWORD ?
val1 DWORD 0
val2 DWORD 0
.code
main PROC
mov ecx, COUNT
L1:
mov LCOUNT, ecx
mov ecx, COUNT2
L2:
mov eax, val1 + (val2 * 16)
call SetTextColor
inc val2
Loop L2
mov ecx, LCOUNT
Loop L1
call DumpRegs
exit
main ENDP
END main
Basically I am doing a nested loop. My thinking is that I simply do a 1 * (1 * 16) then inc the value in a nested loop until 1 * (16 * 16). I am getting the error below
I am getting the error A2026: constant expected
I imagine the error you are getting is at this line:
mov eax, val1 + (val2 * 16)
You just can't do that. If you intend to multiply val2 by 16 and then add val1 to the result, then you need to implement it step by step (you may come across addressing in the form of a+b*c but a and c need to be registers and b can only be 2, 4 or 8, not 16). Try replacing this line with something like this:
mov eax, val2
imul eax, 16
add aex, val1

Resources