I am writing HLA language to determine the input are the same or not the same - hla

PROGRAM 6: Same
Write an HLA Assembly language program that implements a function which correctly identifies when all four parameters are the same and returns a boolean value in AL (1 when all four values are equal; 0 otherwise). This function should have the following signature:
procedure theSame( w:int16; x:int16; y:int16; z:int16 ); #nodisplay; #noframe;
Shown below is a sample program dialogue.
Feed Me W: 215
Feed Me X: 215
Feed Me Y: 480
Feed Me Z: 91
Not the same. AL = 0
Feed Me W: 0
Feed Me X: 0
Feed Me Y: 0
Feed Me Z: 0
Same. AL = 1
Feed Me W: 0
Feed Me X: 221
Feed Me Y: 100
Feed Me Z: 40
Not the same. AL = 0
**My output are almost correct but when I entered
w : 2
x : 2
y : 2
z : 1
"the same" instead of "NOT the same"
Please help with any thoughts that I might be missing.**
I am not sure if register push and pop are the issue.
program Same;
#include ("stdlib.hhf");
static
iDataValue1 : int16 := 0;
iDataValue2 : int16 := 0;
iDataValue3 : int16 := 0;
iDataValue4 : int16 := 0;
procedure theSame( w : int16; x : int16; y : int16; z : int16); #nodisplay; #noframe;
static
returnAddress : dword;
temp: int16;
begin theSame;
pop (returnAddress);
pop (temp);
pop (z);
pop (y);
pop (x);
pop (w);
push (returnAddress);
push (BX);
//Perform Subtask
mov (z, BX);
cmp (y, BX); // Compare z & y
jne ReturnZero;
mov (y, BX);
cmp (x, BX); // Compare y & x
je ReturnOne;
jmp ReturnZero;
mov (x, BX);
cmp (w, BX); // Compare x & w
je ReturnOne;
jmp ReturnZero;
ReturnOne:
mov (1, AL);
jmp ExitSequence;
ReturnZero:
mov (0, AL);
jmp ExitSequence;
ExitSequence:
pop (BX);
ret();
end theSame;
begin Same;
stdout.put ("Feed Me W: ");
stdin.get (iDataValue1);
stdout.put ("Feed Me X: ");
stdin.get (iDataValue2);
stdout.put ("Feed Me Y: ");
stdin.get (iDataValue3);
stdout.put ("Feed Me Z: ");
stdin.get (iDataValue4);
push (iDataValue1);
push (iDataValue2);
push (iDataValue3);
push (iDataValue4);
call theSame;
cmp (AL, 1);
je NumbersAreSame;
jmp NumbersAreDifferent;
NumbersAreSame:
stdout.put ("Same. AL = 1");
jmp EndProgram;
NumbersAreDifferent:
stdout.put ("Not the same. AL = 0");
stdout.newln();
jmp EndProgram;
EndProgram:
end Same;

ENVIRONMENT
HLA (High Level Assembler - HLABE back end, LD linker)
Version 2.16 build 4463 (prototype)
Ubuntu 20.10
SOLUTION
Five values are pushed to the stack when calling theSame(), those are the return address, w, x, y, and z. However in the prologue for theSame() six values are currently popped off of the stack.
begin theSame;
pop (returnAddress);
pop (temp);
pop (z);
pop (y);
pop (x);
pop (w);
The additional pop (temp); seen above causes the temp variable to store the value passed in for z, z to store the value passed in for y, y to store the value passed in for x, x to store the value passed in for w, and w to store the next random value on the stack. Removing the pop (temp); instruction will result in your example case passing.
Feed Me W: 2
Feed Me X: 2
Feed Me Y: 2
Feed Me Z: 1
Not the same. AL = 0
However the following case will still fail due to errors in the comparison logic.
Feed Me W: 1
Feed Me X: 2
Feed Me Y: 2
Feed Me Z: 2
Same. AL = 1
In the following code if z, y, and x are equal then the code will jump to ReturnOne with out checking the value of w. This is corrected by removing the first je ReturnOne; and changing the first jmp ReturnZero; to jne ReturnZero;.
mov (z, BX);
cmp (y, BX); // Compare z & y
jne ReturnZero;
mov (y, BX);
cmp (x, BX); // Compare y & x
je ReturnOne;
jmp ReturnZero;
mov (x, BX);
cmp (w, BX); // Compare x & w
je ReturnOne;
jmp ReturnZero;
EXAMPLE
program Same;
#include("stdlib.hhf");
procedure theSame(w: int16; x: int16; y: int16; z: int16); #nodisplay; #noframe;
begin theSame;
pop(EDX); // Return Address
pop(z);
pop(y);
pop(x);
pop(w);
push(EDX); // Return Address
mov(z, BX);
cmp(y, BX); // Compare z & y
jne ReturnZero;
mov(y, BX);
cmp(x, BX); // Compare y & x
jne ReturnZero;
mov(x, BX);
cmp(w, BX); // Compare x & w
jne ReturnZero;
mov(1, AL);
jmp ExitSequence;
ReturnZero:
mov(0, AL);
ExitSequence:
ret();
end theSame;
begin Same;
stdout.put("Feed Me W: ");
stdin.geti16();
push(AX);
stdout.put("Feed Me X: ");
stdin.geti16();
push(AX);
stdout.put("Feed Me Y: ");
stdin.geti16();
push(AX);
stdout.put("Feed Me Z: ");
stdin.geti16();
push(AX);
call theSame;
cmp(AL, 1);
jne NumbersAreDifferent;
stdout.put("Same. AL = 1");
jmp EndProgram;
NumbersAreDifferent:
stdout.put("Not the same. AL = 0");
EndProgram:
end Same;

Related

c++ inline at&t syntax num to the power of num function it always returns either 0 or 4 on the number 2

Here is my code:
__asm__ ("movl %3, %%ecx\n"
"movl $0, %%edx\n"
"movl %2, %%eax\n"
"1:\n"
"movl %2, %%ebx\n"
"movl %%ecx, %1\n" // Debugging
//"movl %%edx, %3\n" // Debugging
//"movl %%eax, %4\n" // Debugging
"imul %%ebx, %%eax\n"
"inc %%edx\n"
"cmp %%edx, %%ecx\n"
"jle 1b\n"
"movl %%eax, %0\n"
: "=r" (retval), "=r" (ecxval)
: "r" (val), "r" (pow));
(ecxval) is for debugging my code. (retval) is the return variable.
When I use 2 I always get either 4 or 0 which is weird.
(1:) is my label for my loop.
(val) is the input value.
(pow) is the power number.
for example val: 2, pow: 5 is 2^5.
At the start of the program ecx is set to the val, edx is the counter so its set to 0, eax is set to the val.
In the loop my code should move the contents of val to ebx multiply eax by ebx and the result is put into eax, then edx is increased by 1 and edx is compared to ecx and if less than or equal to it jumps and at the end the contents of eax are moved into the return value.
I've tried all ways I can think of to debug but with 2^(an even number) it always results in 4 and 2^(an uneven number) it always results in 0. But the expected result is for example 2^2 = 4, 2^3 = 8.

Assembly variables

I am new to assembly and am confused how some variables magically obtain values from nowhere, like in this code I have (program shifts by one ASCII code all entered symbols)
.model small
.stack 100h
.data
Enterr db 10, 13, "$"
buffer db 255
number db ?
symb db 255 dup (?)
.code
START:
MOV ax, #data
MOV ds, ax
MOV ah, 10
MOV dx, offset buffer
INT 21h
MOV ah, 9
MOV dx, offset ENTERR
INT 21h
MOV bx, offset symb
MOV cl, number
MOV ch, 0
CMP cx, 0
JE terminate
cycle:
INC byte ptr [bx]
INC bx
LOOP cycle
MOV byte ptr [bx], '$'
MOV ah, 9
MOV dx, offset symb
INT 21h
terminate:
MOV ah, 4Ch
MOV al, 0
INT 21h
END START
Just before the loop, cx has the number of symbols entered, and cycle begins to take pace from there on. This value of cx was obtained when variable "number" is copied to cl. How did variable "number" obtained such a value? Replacing
MOV cl, number
with
MOV cl, [number]
Does not effect the program. Why is that? Does every variable defined by
variable db ?
has the same value, i.e. number of symbols entered?(I am using TASM)

CPU not calling IRQ0?

I am writting an OS and trying to use the PIT. I have a handler written and wrote an ISR entry for the IRQ0 (Interrupt 32). The handler is not being called at all. I am pretty sure I am not putting the ISR entry in right. Any suggestions? Here is my ASM code
mov dword EAX, irq_common_stub
mov byte [_NATIVE_IDT_Contents + 0x100], AL
mov byte [_NATIVE_IDT_Contents + 0x101], AH
mov byte [_NATIVE_IDT_Contents + 0x102], 0x8
mov byte [_NATIVE_IDT_Contents + 0x105], 0x8E
shr dword EAX, 0x10
mov byte [_NATIVE_IDT_Contents + 0x106], AL
mov byte [_NATIVE_IDT_Contents + 0x107], AH
My code to init the PIT is
public static void PIT_Init(uint frequency)
{
uint divisor = 1193180 / frequency;
GruntyOS.IO.Ports.Outb(0x43, 0x36);
byte l = (byte)(divisor & 0xFF);
byte h = (byte)((divisor >> 8) & 0xFF);
GruntyOS.IO.Ports.Outb(0x40, l);
GruntyOS.IO.Ports.Outb(0x40, h);
}
The handler is
public static void HandlePIT()
{
GruntyOS.IO.Ports.Outb(0xA0, 0x20);
GruntyOS.IO.Ports.Outb(0x20, 0x20);
print("Tick: " + Tick.ToString());
Tick++;
}
Which is called from
irq_common_stub:
pusha
mov ax, ds
push eax
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call System_Void__GruntyOS_Entry_HandlePIT__
pop ebx
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
popa
add esp, 8
sti
iret
Maybe this might help. Its a simple kernel
that is capable of handling IRQs and Exceptions.
http://www.osdever.net/bkerndev/Docs/irqs.htm
http://www.ni.com/white-paper/2874/en

Pointers and Loops

This one has been bothering me for a while now: Is there a difference (e.g. memory-wise) between this
Pointer *somePointer;
for (...)
{
somePointer = something;
// do stuff with somePointer
}
and this
for (...)
{
Pointer *somePointer = something;
// do stuff with somePointer
}
If you want to use the pointer when you're done with the loop, you need to do the first one.
Pointer *somePointer;
Pointer *somePointer2;
for(loopA)
{
if(meetsSomeCriteria(somePointer)) break;
}
for(loopB)
{
if(meetsSomeCriteria(somePointer2)) break;
}
/* do something with the two pointers */
someFunc(somePointer,somePointer2);
Well, first, in you second example somePointer will be valid only inside the loop (it's scope), so if you want to use it outside you have to do like in snippet #1.
If we turn on assembly we can see that the second snipped needs only 2 more instructions to execute:
Snippet 1:
for(c = 0; c <= 10; c++)
(*p1)++;
0x080483c1 <+13>: lea -0x8(%ebp),%eax # eax = &g
0x080483c4 <+16>: mov %eax,-0xc(%ebp) # p1 = g
0x080483c7 <+19>: movl $0x0,-0x4(%ebp) # c = 0
0x080483ce <+26>: jmp 0x80483e1 <main+45> # dive in the loop
0x080483d0 <+28>: mov -0xc(%ebp),%eax # eax = p1
0x080483d3 <+31>: mov (%eax),%eax # eax = *p1
0x080483d5 <+33>: lea 0x1(%eax),%edx # edx = eax + 1
0x080483d8 <+36>: mov -0xc(%ebp),%eax # eax = p1
0x080483db <+39>: mov %edx,(%eax) # *p1 = edx
0x080483dd <+41>: addl $0x1,-0x4(%ebp) # c++
0x080483e1 <+45>: cmpl $0xa,-0x4(%ebp) # re-loop if needed
0x080483e5 <+49>: jle 0x80483d0 <main+28>
Snippet 2:
for(c = 0; c <= 10; c++) {
int *p2 = &g;
(*p2)--;
}
0x080483f0 <+60>: lea -0x8(%ebp),%eax # eax = &g
0x080483f3 <+63>: mov %eax,-0x10(%ebp) # p2 = eax
0x080483f6 <+66>: mov -0x10(%ebp),%eax # eax = p2
0x080483f9 <+69>: mov (%eax),%eax # eax = *p2
0x080483fb <+71>: lea -0x1(%eax),%edx # edx = eax - 1
0x080483fe <+74>: mov -0x10(%ebp),%eax # eax = p2
0x08048401 <+77>: mov %edx,(%eax) # *p2 = edx
0x08048403 <+79>: addl $0x1,-0x4(%ebp) # increment c
0x08048407 <+83>: cmpl $0xa,-0x4(%ebp) # loop if needed
0x0804840b <+87>: jle 0x80483f0 <main+60>
Ok, the difference is in the first two instructions of snippet #2 which are executed at every loop, while in the first snippet they're executed just before entering the loop.
Hope I was clear. ;)
Well, with the first version you only have to release once, after the loop. With the second version you can't use the pointer from outside the loop, so you need to release inside the loop. Memory-wise it shouldn't matter that much, but you do have allocation overhead in your second example I think.
check out a similar answer on stackoverflow here with some good answers. However this is probably compiler/language independent...

How can I optimize my C / x86 code?

int lcm_old(int a, int b) {
int n;
for(n=1;;n++)
if(n%a == 0 && n%b == 0)
return n;
}
int lcm(int a,int b) {
int n = 0;
__asm {
lstart:
inc n;
mov eax, n;
mov edx, 0;
idiv a;
mov eax, 0;
cmp eax, edx;
jne lstart;
mov eax, n;
mov edx, 0;
idiv b;
mov eax, 0;
cmp eax, edx;
jnz lstart;
}
return n;
}
I'm trying to beat/match the code for the top function with my own function (bottom). Have you got any ideas how I can optimize my routine?
PS. This is just for fun.
I would optimize by using a different algorithm. Searching linearly like you are doing is super-slow. It's a fact that the least common mulitple of two natural numbers is the quotient of their product divided by their greatest common divisor. You can compute the greatest common divisor quickly using the Euclidean algorithm.
Thus:
int lcm(int a, int b) {
int p = a * b;
return p / gcd(a, b);
}
where you need to implement gcd(int, int). As the average number of steps in the Euclidean algorithm is O(log n), we beat the naive linear search hands down.
There are other approaches to this problem. If you had an algorithm that could quickly factor integers (say a quantum computer) then you can also solve this problem like so. If you write each of a and b into its canonical prime factorization
a = p_a0^e_a0 * p_a1^e_a1 * ... * p_am^e_am
b = p_b0^e_b0 * p_b1^e_b1 * ... * p_bn^e_bn
then the least common multiple of a and b is the obtained by taking for each prime factor appearing in at least one of the factorizations of a and b, taking it with the maximum exponent that it appears in the factorization of a or b. For example:
28 = 2^2 * 7
312 = 2^3 * 39
so that
lcm(28, 312) = 2^3 * 7 * 39 = 2184
All of this is to point out that naive approaches are admirable in their simplicity but you can spend all day optimizing every last nanosecond out of them and still not beat a superior algorithm.
I'm going to assume you want to keep the same algorithm. This should at least be a slightly more efficient implementation of it. The main difference is that the code in the loop only uses registers, not memory.
int lcm(int a,int b) {
__asm {
xor ecx, ecx
mov esi, a
mov edi, b
lstart:
inc ecx
mov eax, ecx
xor edx, edx
idiv esi
test edx, edx
jne lstart
mov eax, ecx;
idiv edi
test edx, edx
jnz lstart
mov eax, ecx
leave
ret
}
}
As Jason pointed out, however, this really isn't a very efficient algorithm -- multiplying, finding the GCD, and dividing will normally be faster (unless a and b are quite small).
Edit: there is another algorithm that's almost simpler to understand, that should also be a lot faster (than the original -- not than multiplying, then dividing by GCD). Instead of generating consecutive numbers until you find one that divides both a and b, generate consecutive multiples of one (preferably the larger) until you find one that divides evenly by the other:
int lcm2(int a, int b) {
__asm {
xor ecx, ecx
mov esi, a
mov edi, b
lstart:
add ecx, esi
mov eax, ecx
xor edx, edx
idiv edi
test edx, edx
jnz lstart
mov eax, ecx
leave
ret
}
}
This remains dead simple to understand, but should give a considerable improvement over the original.