How to change the value of a variable in assembly - variables

I am working on some code for my port of MikeOS. It is written in NASM x86 16 bit assembly. I am trying to change a variable that I made to have a different value. It compiles with no errors, but when I call os_print_string, it prints some wierd ASCII characters. Here is the code:
BITS 16
ORG 32768
%INCLUDE "mikedev.inc"
start:
mov si, test2 ; give si test 2 value
mov [test1], si ; give test 1 si's value
mov si, test1 ;now give test1's value to si
call os_print_string ; and print
test2 db "adsfasdfasdf", 0
test1 db "asdf", 0
This code is redundant, I know. I just need a n explanation on how to change a variable's value. Thaks in advance!
-Ryan

Another good old question, here is the answer you waited for 6.83 years :)
BITS 16
ORG 32768
%INCLUDE "mikedev.inc"
start:
mov si, test2
mov di, test1
.loop:
lodsb
or al, al
je .done
stosb
jmp .loop
.done:
mov si, test1
call os_print_string
test2 db "adsfasdfasdf", 0
test1 db "asdf ", 0
Make sure the char arrays have the same length or this will break ^^
But i am sure you know that by now ^^

Related

MSP430 - Bad constant when using ORG 01100h

#include "msp430g2553.h" // #include <msp430.h> - can be used as well
;-------------------------------------------------------------------------------
ORG 0x1100h
ID_F DB 0,3,9,1,0,4,9,0
ID_S DB 0,5,1,8,9,3,9,1
Size DW 16
;-------------------------------------------------------------------------------
MODULE PortLeds
PUBLIC First_SW, Second_SW, Third_SW;, Else_SW
;EXTERN ;Delay_Sec
RSEG CODE
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
Third_SW BIT.B #0x04, &P1IN
CLR R10 ; Index register
THIRD_LOOP MOV.B ID_F(R10), R15 ; Counter from 0 to ff-255
MOV.B R15, &P2OUT ; Save value
MOV.B #0x06, R13
Wait3 mov.w #0xFFFF,R14 ; Delay to R14
L3 dec.w R14 ; Decrement R14
jnz L3 ; Delay over?
DEC.B R13
JNZ Wait3
INC R10
CMP Size, R10
JL THIRD_LOOP
For some reason, when I am Third_SW, I reach this error:
pre_lab3_function.s43
Error[6]: Bad constant C:\Users\blala\OneDrive\Desktop\lab_3_new\pre_lab3_function.s43 3
Error while running Assembler
It appears on the org0110h, why is it happening? I am stuck for one day already because of it.
Any other code ( as you see its Third ) works pretty good, only Third which I need to use ID_F ID_S and Size, are the problem.

Assembly - how to increase a variable by 2

How do I increase a variable by 2?
I am using Assembly x86 and TASM.
Thanks for help.
Try this :
.stack 100h
.data
my_var dw ?
.code
mov ax,#data
mov ds,ax
mov my_var, 5
add my_var, 2 ;<=== INCREASE BY 2 ( 5+2 ).
mov ax,4c00h
int 21h
If you are using IDEAL mode :
add [ my_var ], 2 ;<=== INCREASE BY 2 ( 5+2 ).

Getting capital letters MASM x86

I am having some problems with getting the amount of uppercase letters in a string that will be passed in by a user. I have to write it in masm. My question is can i use an:
AND al, some bitstream
;TO DO LOGIC HERE
to get only capital letters? My code correctly gets the amount of lowercase letters, I just cant seem to figure out the capital letters. Also, this string has some random characters in it, such as: (<)>?$##&. Is it as simple as that? or do I need a lot more logic to accomplish this?
Something like this?
jmp getNext
getNext: mov al,[esi]
cmp al,0
je exitProc ;exit loop
cmp al,'a'
jl noChange ;increases my counters
cmp al,'z'
jle toUpperCase ;counts lowercase
cmp AL,'A'
jl noChange
cmp AL,'Z'
jg noChange
jl toCount ;counts uppercase
I keep getting 0 as my answer and cannot figure out why. I am clearly very challenged by MASM.
It seems that my toCount never gets called. Instead the lines:
cmp AL,'A'
jl noChange
cmp AL,'Z'
jl toCount ;counts uppercase
Seem to only call noChange. Which is causing the value increased in toCount to never be called. I still cannot figure out what is wrong with this. It is the same exact thing as the test for the lowercase letter, except using the captial letters in the cmp.
What needs to be done is the following:
cmp al,'A'
jl noChange ;inc counter
cmp al,'Z'
jle toCount ;count uppercase
cmp al,'a'
jl noChange ;inc counter
cmp al,'z'
jle toUpperCase ;count lowercase
In ASCII 'A' = 65 and 'Z' = 90. 'a' = 97 and 'z' = 122. My issue was that I was testing for the higher ASCII characters first, which would ignore any ASCII characters from 65-90 (A-Z).

Which variable size to use (db, dw, dd) with x86 assembly?

I don't know what all the db, dw, dd, things mean.
I have tried to write this little script that does 1+1, stores it in a variable and then displays the result. Here is my code so far:
.386
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
.data
num db ? ; set variable . Here is where I don't know what data type to use.
.code
start:
mov eax, 1 ; add 1 to eax register
mov ebx, 1 ; add 1 to ebx register
add eax, ebx ; add registers eax and ebx
push eax ; push eax into the stack
pop num ; pop eax into the variable num (when I tried it, it gave me an error, i think thats because of the data type)
invoke StdOut, addr num ; display num on the console.
invoke ExitProcess ; exit
end start
I need to understand what the db, dw, dd things mean and how they affect variable setting and combining and that sort of thing.
Quick review,
DB - Define Byte. 8 bits
DW - Define Word. Generally 2 bytes on a typical x86 32-bit system
DD - Define double word. Generally 4 bytes on a typical x86 32-bit system
From x86 assembly tutorial,
The pop instruction removes the 4-byte data element from the top of
the hardware-supported stack into the specified operand (i.e. register
or memory location). It first moves the 4 bytes located at memory
location [SP] into the specified register or memory location, and then
increments SP by 4.
Your num is 1 byte. Try declaring it with DD so that it becomes 4 bytes and matches with pop semantics.
The full list is:
DB, DW, DD, DQ, DT, DDQ, and DO (used to declare initialized data in the output file.)
See: http://www.tortall.net/projects/yasm/manual/html/nasm-pseudop.html
They can be invoked in a wide range of ways: (Note: for Visual-Studio - use "h" instead of "0x" syntax - eg: not 0x55 but 55h instead):
db 0x55 ; just the byte 0x55
db 0x55,0x56,0x57 ; three bytes in succession
db 'a',0x55 ; character constants are OK
db 'hello',13,10,'$' ; so are string constants
dw 0x1234 ; 0x34 0x12
dw 'A' ; 0x41 0x00 (it's just a number)
dw 'AB' ; 0x41 0x42 (character constant)
dw 'ABC' ; 0x41 0x42 0x43 0x00 (string)
dd 0x12345678 ; 0x78 0x56 0x34 0x12
dq 0x1122334455667788 ; 0x88 0x77 0x66 0x55 0x44 0x33 0x22 0x11
ddq 0x112233445566778899aabbccddeeff00
; 0x00 0xff 0xee 0xdd 0xcc 0xbb 0xaa 0x99
; 0x88 0x77 0x66 0x55 0x44 0x33 0x22 0x11
do 0x112233445566778899aabbccddeeff00 ; same as previous
dd 1.234567e20 ; floating-point constant
dq 1.234567e20 ; double-precision float
dt 1.234567e20 ; extended-precision float
DT does not accept numeric constants as operands, and DDQ does not accept float constants as operands. Any size larger than DD does not accept strings as operands.

Small assembly code sequence optimization (intel x86)

I am doing some exercises in assembly language and I found a question about optimization which I can't figure out. Can anyone help me with them
So the question is to optimize the following assembly code:
----------------------------Example1-------------------------
mov dx, 0 ---> this one I know-> xor dx,dx
----------------------------Example2------------------------
cmp ax, 0
je label
----------------------------Example3-------------------------
mov ax, x
cwd
mov si, 16
idiv si
----> Most I can think of in this example is to subs last 2 lines by idiv 16, but I am not sure
----------------------------Example4-------------------------
mov ax, x
mov bx, 7
mul bx
mov t, ax
----------------------------Example5---------------------------
mov si, offset array1
mov di, offset array2
; for i = 0; i < n; ++i
do:
mov bx, [si]
mov [di], bx
add si, 2
add di, 2
loop do
endforloop
For example 2, you should look at the and or test opcodes. Similar to example 1, they allow you to remove the need for a constant.
For example 4, remember that x * 7 is the same as x * (8 - 1) or, expanding that, x * 8 - x. Multiplying by eight can be done with a shift instruction.
For example 5, you'd think Intel would have provided a much simpler way to transfer from SI to DI, since that is the whole reason for their existence. Maybe something like a REPetitive MOVe String Word :-)
For example three, division by a power of two can be implemented as a right shift.
Note that in example 5, the current code fails to initialize CX as needed (and in the optimized version, you'd definitely want to do that too).