How do I print 0,2,4,6,... in assembly language? - algorithm

I have an assignment from my comp. system org. subject and unfortunately I'm kind of new when it comes to assembly language. I'm supposed to write a program that displays the numbers 0,2,4,6,8,10 respectively. How would I go about this?
Maybe this'll answer my question: (Reactions please)
.model small
.stack 100H
.data
.code
call proc
mov cx,5
mov dx,0
L1:
mov bx,2
add dx,bx
mov ah,02h
loop L1
int 21
endp

Go see your lecturer and/or tutor and ask for advice. That's what they're there for. You haven't given us anywhere near enough info to help you out.
Here's what I think your ABCD program should look like. I suggest you use it as a baseline to try to make a 0 2 4 ... version.
model proc
.stack 100H
.data
.call
main proc
mov cx,10 ; 10 loops only.
mov dx,40h ; start dx at 'A' - 1.
L1:
inc dx ; move to next character.
mov ah,02h ; int 21,02 is print character.
int 21h
loop L1 ; loop until cx is 0
mov ax,4c00h ; int 21,4c is exit with al holding exit code.
int 21
endp
When you've at least had a go at converting this, post the code and we'll critique what you've done.
If you're taught something, it never lasts but, if you learn something, it lasts forever (alcohol-addled braincells notwithstanding :-).
Int 21 is the DOS interrupt which allows assembler programs to use various DOS functions. It's conceptually a huge switch statement based on the AH register which is why you'll see things like Int 21 Fn 02, which means execute mov ah,2 followed by int 21.
Int 21 Fn 02 will take the contents of DL and output that to the screen. So the sequence:
mov ah,02h
mov dl,41h
int 21h
will output the 'A' character (0x41).
Similarly, Int 21 Fn 4c will exit the current running process.

I'm sure your class gave you some education here.
Can you code enough assembly to print one or two numbers?
Can you code enough to calculate the numbers, even if you can't print them?
Post that much code, and you may find help here.
Otherwise, you're asking others to actually do your homework for you.

Assembly language is a symbolic representation of the numeric machine codes and other constants needed to program a particular CPU (or architecture). So assembly language for Macs (most recently Intel's X86) is different from that used to on the iPhone - ARM.
Your teacher is also probably expecting you to realise the difference between the binary form of the number you will count with, and the ASCII format you will use to display to the screen.

You do know there is more than one flavor of "Assembly Language."

You can do it exactly like the program which prints A, B, C, D, etc.: except that instead of starting at 'A', start at '0; and instead of increasing by 1 each time (from 'A' to 'B'), increase by 2 (from '0' to '2').
After printing '0', '2', '4', '6', and '8', the next number that you want to print is '10'.
To print '10', you can print '1' followed by '0'. Or, instead of invoking int 21 with ah=2 (which prints one character at a time), you can set ah=9 to print a string (set ds:dx to a block of memory which contains "10$").
Later you suggested the following solution and asked for criticism:
.model small
.stack 100H
.data
.code
main proc
call defineuser1
call defineuser2
mov cx,5
userdefine1 proc
L1:
mov dx,0
mov bx,2
add dx,bx
mov ah,02h
loop L1
int 21h
endp
userdefine2 proc
mov ah, 4ch
int 21h
userdefine2
endp
My criticisms are as follows:
defineuser1 doesn't exist (I think you mean userdefine1)
setting cx needs to be inside (not before) the procedure
invoking int 21 needs to be inside (not outside) the loop
you need special handling for "10" as I mentioned above
There's a difference between '0' (the ASCII character/digit) and 0 (the number) ... you need to print the character/digit, not the number
You need to learn to test your code (write it, step through it with debugger, and debug it), preferably before you post questions about it.

You would have a counter beginning at zero and repeatedly increment it by two, printing the result.

.model small
.stack 100H
.code
.data
var2 DB "10$"
main proc
mov cx,4
mov ax,0
mov dl,al
add dl,30h
mov ah,02h
int 21h
mov ax,0
var1:
add ax,2
mov dl,al
add dl,30h
mov bx,ax
mov ah,2h
int 21h
mov ax,bx
loop var1
mov ax,#data
mov ds,ax
mov dx,offset var2
mov ah,09h
int 21h
main endp
end main
I'm new in computer science and when i saw this question i just wanted to try it. I have managed in doing it and here is the code

MOV AX, 0
MOV BX, 2
ADDLOOP:
ADD AX, BX
CMP AX, 10
JE DONE
JMP ADDLOOP
DONE:
Ok. That's my best attempt. Lots of details left out. I should also mention that I have no frigging clue how to print a char to the screen.
Like others have mentioned, you didn't specify which assembly language so I chose x86.
Finally, go talk to your instructors, they'll help you much more than we can.

Are you using a macro for the output?
should be something like...
mov eax, 0
myloop: cmp eax, 10
jg done
output macro eax
add eax, 2
jmp myloop
done:
of course that's for 8086 assembly.

Related

How to replace a store of EAX with a store of an immediate constant?

From my previous question, I asked how to change the nation code to what I needed it to be. I explored in the disassembly more and I found out exactly where I needed this change to be. In other files, the code seems to be:
mov ds:dword_73A9C8, 1
Where the file I'm trying to edit has it like
mov ds:dword_73A9C8, eax
I've tried to edit the file in IDA by hex to match it to the first line of code, however, the function, even after extending its length, seems to break each time I edit it.
The question I have is how can I change it from having eax being moved to having 1 being moved without breaking the function
sub_4A2B60 proc near
arg_0= dword ptr 4
mov eax, [esp+arg_0]
mov ds:dword_73A9C8, eax
retn
sub_4A2B60 endp
You could replace the 4 byte instruction mov eax, [esp + 4] with the sequence xor eax, eax inc eax nop that also has 4 bytes.
If 1 is what you want, then the return value in EAX should probably also be 1.

Outputting Az-Za in MS-Debug

I'm currently struggling in outputting AzByCx in ms debug since I don't really know too much about it.
Included here are the Basic commands that my teacher sent to us.
I can output A-Z easily, but not AzBxCy, there's not much of a detailed tutorial online so I came here to ask.
-e 200 "Az"
-a
1BD8:0100 mov bx, word [200]
1BD8:0104 mov cx, 3
1BD8:0107 mov ah, 2
1BD8:0109 mov dl, bl
1BD8:010B int 21
1BD8:010D mov dl, bh
1BD8:010F int 21
1BD8:0111 add bx, FF01
1BD8:0115 loop 109
1BD8:0117 mov dl, 0D
1BD8:0119 int 21
1BD8:011B mov dl, 0A
1BD8:011D int 21
1BD8:011F mov ax, 4C00
1BD8:0122 int 21
1BD8:0124
-g
AzByCx
What does this do?
initialises word at ds:200h to the string "Az" (little endian low byte is "A", high byte is "z")
use A command to assemble the following program:
load from memory into register bx (to initialise the register without having to look up the numeric ASCII codepoints)
set up cx as loop counter for three iterations
set up register ah for the interrupt 21h service 02h (display character in dl)
display character read from bl (low byte of bx)
display character from bh (high byte of bx)
add 1 to bl and -1 (in two's complement resulting in 0FFh) to bh which increments the codepoint in bl and decrements the one in bh
loop back to display subsequent letters
display a linebreak (codepoints 13 and 10, or 0Dh 0Ah) to make the output easier to read
terminate program
use G command to run the program
Microsoft DEBUG.EXE can indeed be used to write a simple program in Intel-syntax assembly, see this example. Replace the string definition db "Hello world$" with db "AzByCx$" and you're done.
However, this is definitely not a good way how to learn assembly language.
Find a better teacher.

How do I check if my assembly 8086 program runs well

I want to put numbers from 0 - 9 to memory cells 400h to 409h.
So for example at 400h -> 0 (put 0) and at 401h -> 1 (put 1) ..... 409h (put 9).
This is my code so far: (I dont know if it works)
IDEAL
MODEL small
STACK 100h
DATASEG
;----------
;----------
CODESEG
start:
mov ax , #data
mov ds , ax
mov es, ax
;----------
mov si , 400h
mov cx , 10
mov al , 0
agian:
mov [si],al
inc si
inc al
loop agian
;--------
exit:
mov ax,4c00h
int 21h
END start
There's a very simple way to see if your program works. Just write the values in the video memory. That way you'll know if it works.
start:
mov ax, 0B800h ;NEW
mov ds, ax
mov es, ax
;----------
mov si, 400h
mov cx, 10
mov al, 48 ;NEW value 0 -> character 0
agian:
mov [si], al
add si, 2 ;NEW 1 character occupies 2 bytes in video memory
inc al
loop agian
mov ah,00h ;NEW wait for a keystroke so you can actually see
int 16h ;NEW ... the output
If you can invest the time you could learn to use the DOS utility DEBUG.EXE. Amongst other things it allows you to single step your program and view memory .
The easiest way to check if your ASM code is working the way you expect is to run it in a debugger. If you're running on Windows, OllyDbg 2 would be a good candidate — it will show you the current values of the registers, state of the stack, etc., so you can see how they change as you step through your code. You can modify the code from inside OllyDbg too.
You can write breakpoints in your code with the int 3 instruction, or use the debugger to place breakpoints at runtime.

NASM jmp wonkiness

I'm writing a Forth inner interpreter and getting stuck at what should be the simplest bit. Using NASM on Mac (macho)
msg db "k thx bye",0xA ; string with carriage return
len equ $ - msg ; string length in bytes
xt_test:
dw xt_bye ; <- SI Starts Here
dw 0
db 3,'bye'
xt_bye dw $+2 ; <- Should point to...
push dword len ; <-- code here
push dword msg ; <--- but it never gets here
push dword 1
mov eax, 0x4 ; print the msg
int 80h
add esp, 12
push dword 0
mov eax, 0x1 ; exit(0)
int 80h
_main:
mov si,xt_test ; si points to the first xt
lodsw ; ax now points to the CFA of the first word, si to the next word
mov di,ax
jmp [di] ; jmp to address in CFA (Here's the segfault)
I get Segmentation Fault: 11 when it runs. As a test, I can change _main to
_main:
mov di,xt_bye+2
jmp di
and it works
EDIT - Here's the simplest possible form of what I'm trying to do, since I think there are a few red herrings up there :)
a dw b
b dw c
c jmp _my_actual_code
_main:
mov si,a
lodsw
mov di,ax
jmp [di]
EDIT - After hexdumping the binary, I can see that the value in b above is actually 0x1000 higher than the address where label c is compiled. c is at 0x00000f43, but b contains 0x1f40
First, it looks extremely dangerous to use the 'si' and 'di' 16-bit registers on a modern x86 machine which is at least 32-bit.
Try using 'esi' and 'edi'. You might be lucky to avoid some of the crashes when 'xt_bye' is not larger than 2^16.
The other thing: there is no 'RET' at the end of xt_bye.
One more: see this linked question Help with Assembly. Segmentation fault when compiling samples on Mac OS X
Looks like you're changing the ESP register to much and it becomes unaligned by 16 bytes. Thus the crash.
One more: the
jmp [di]
may not load the correct address because the DS/ES regs are not used thus the 0x1000 offset.

Outputting registers to the console with MASM

I'm one day into learning ASM and I've done a few tutorials, and even successfully modified the tutorial content to use jmp and cmp, etc instead of the MASM .if and .while macros.
I've decided to try and write something very, very simple to begin with before I continue with more advanced tutorials. I'm writing a Fibonacci number generator. Here is the source I have 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
.code
start:
mov eax, 1
mov ecx, 1
_a:
push eax
add eax, ecx
pop ecx
; Jump to _b if there is an overflow on eax
; Print Values Here
jmp _a
_b:
push 0
call ExitProcess
end start
I intend to check for overflows on eax/ecx but right now I'm just interested in displaying the values of eax/ecx on the screen.
I know how to push the address of a constant string from .data and call StdOut which was the first example in the hello world tutorial, but this appears to be quite different (?).
There is this code provided by Microsoft itself
http://support.microsoft.com/kb/85068
Note that this code outputs AX register on 16 bit systems. But you can get the idea, you just need to convert AX value into ASCII characters by looping through each character. Skip the interrupts part and use your StdOut function.
mov dx, 4 ; Loop will print out 4 hex characters.
nexthex:
push dx ; Save the loop counter.
mov cl, 4 ; Rotate register 4 bits.
rol ax, cl
push ax ; Save current value in AX.
and al, 0Fh ; Mask off all but 4 lowest bits.
cmp al, 10 ; Check to see if digit is 0-9.
jl decimal ; Digit is 0-9.
add al, 7 ; Add 7 for Digits A-F.
decimal:
add al, 30h ; Add 30h to get ASCII character.
mov dl, al
;Use StdOut to print value of dl
;mov ah, 02h ; Prepare for interrupt.
;int 21h ; Do MS-DOS call to print out value.
pop ax ; Restore value to AX.
pop dx ; Restore the loop counter.
dec dx ; Decrement loop counter.
jnz nexthex ; Loop back if there is another character
; to print.
See here as well:
http://www.masm32.com/board/index.php?PHPSESSID=fa4590ba57dbaad4bc44088172af0b49&action=printpage;topic=14410.0

Resources