I'd like to write a program that counts the amount of specific symbols in string using scasb and masm32, I found the example, but I couldn't figure out why i'm getting errors.
Here's the part of code:
.data
str db '. . .'
len_str=$-str
.code
start:
mov ax,#data
mov ds,ax
mov es,ax
lea di,str
mov cx, len_str
mov al,' '
mov bx,0
cld
cycl:
repe scasb
jcxz exit
inc bx
jmp cycl
exit:
getting
A2008 syntax error db, str
A2006 syntax error len_str
A2148 invalid symbol type in expression: exit
A2004: symbol type conflict
str is an instruction, it is the mnemonic for Store Task Register. You cannot use it as a label name as you are trying to do. Name it something else and that should take care of your errors
Related
I tried a string reversal program, but emu8086 is showing me an error message
(12)offset calculation error
What is wrong with the line LEA DI,STR2+LEN-1 ?
DATA SEGMENT
STR1 DB 'HELLO'
LEN EQU $-STR1
STR2 DB 20 DUP(0)
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, ES:DATA
START: MOV AX,DATA
MOV DS,AX
MOV ES,AX
LEA SI,STR1
LEA DI,STR2+LEN-1
MOV CX,LEN
UP: CLD
LODSB
STD
STOSB
LOOP UP
MOV AH,4CH
INT 21H
CODE ENDS
END START
I'm not using emu8086, but the following will correct your line 12:
mov di, offset STR2 + LEN - 1
The shorter way to obtain an address is writing mov si, offset STR1 (uses 3 bytes) instead of lea si, STR1 (uses 4 bytes).
The loop ends with the direction flag still set!
It will always be a good idea to have the direction flag cleared before invoking any system function:
...
LOOP UP
CLD ; Add this to clear direction flag
MOV AH,4CH ; DOS.Terminate
INT 21H
...
I am trying to write skewed Text on Terminal via assembly to get my skills going.
Example [] = spaces :
H
[]E
[][]L
[][][] L
[][][][] O
But I seem to run into a timeout, because I am trying to move a character between registers / get the character via memory address - like getting a char at an index. But it won't really work. I tried working with allocating a byte to increment in the .bss section before, but that lead to a different error which I couldn't work around (relocation truncated to fit: R_X86_64_8 against `.bss')
Maybe there is a better approach to handle this, and if you could help me get on the right path I would be so so happy. To get more context, here is the 'problematic' snippet of my latest code.
inc rcx ; increase pointer of rcx
space_loop:
push rdi ;save destination register
cmp byte [rcx], 0 ;end of string found
je eos ; jump to exit subroutine
mov rax, 4; SYS Write
mov rbx, 0 ; STDOUT
cmp rsp,[rbp] ; compare spaceIndex to String Index
je print_char
mov rdi, space ;print space
mov rdx,1 ; length = 1
syscall
inc byte [rsp] ; increase spaceIndex
jnz space_loop
print_char:
;print out char
mov rax, 4
mov rbx, 0
mov rcx,[rcx] ; <- this line breaks it dont know how to access index here
mov rdx, 1
syscall
call new_Line ; make line break
inc rcx ; increase rcx counter
inc byte [rbp] ; increase index counter
mov byte [rsp], 0 ;reset space counter
jmp space_loop; next Line
My code is required to have a string that will be printed to the console, alongside a string length counting program that will count it instead of manually putting length of string in edx register. But i am getting strange characters printed right after the string is printed.
global _start
section .text
_start:
mov edi, message
call _strlen
mov edx, eax
mov eax, 4
mov ebx, 1
mov ecx, message
int 80h
mov eax, 1
mov ebx, 5
int 80h
section .data
message: db "My name is Stanley Hudson", 0Ah
_strlen:
push ebx
push ecx
mov ebx, edi
xor al, al
mov ecx, 0xffffffff
repne scasb ; REPeat while Not Equal [edi] != al
sub edi, ebx ; length = offset of (edi – ebx)
mov eax, edi
pop ebx
pop ecx
ret
Here is the output
strlen searches for a 0 byte terminating the string, but your string doesn't have one, so it goes until it does find a zero byte and returns a value that's too large.
You want to write
message: db "My name is Stanley Hudson", 0Ah, 0
; ^^^
Another bug is that your _strlen function is apparently in the .data section, because you didn't go back to section .text after your string. x86-32 doesn't have the NX bit so the .data section is executable and everything still works, but it's surely not what you intend.
To get rid of the special characters write the strlen function before the start process and create a new register for the newline character
I looked all over google for ways to do this, I found some but I really found them to be overly complex for what I need. For starters, I need this to be done through a loop, the place where I'm putting my strings is also initially empty, so I'm sure that is bound to create some issues.
Anyway this is my code:
%include "io.mac"
.DATA
filename_msg db 'Enter the file name: ', 0
number_prompt_msg db 'Enter the number of bases: ',0 ;asks for the number of bases to be used
finish_msg db 'Operation completed, DNA file generated',0 ;tells the user when the file is complete
error_msg db 'Operation failed, please try again', 10
base_A db 'A',0
base_C db 'C',0
base_G db 'G',0
base_T db 'T',0
base_length equ $ - base_A
;----------------------------------------------------------------------------------------------------
.UDATA
number_of_bases rest 1 ;defined by the user
random_number resb 1
filename: resd 20 ;defined by the user
base rest 1
file_descriptor resd 1 ;used to generate the file
characters_to_write rest 1
;-------------------------------------------------------------------
;start of code, and message prompts for the user
.CODE
.STARTUP
;asks user for filename
ask_details:
PutStr filename_msg
GetStr filename, 300
;asks user for the number of bases
PutStr number_prompt_msg
GetLInt [number_of_bases]
;------------------------------------------------------------
;file creation
mov EAX, 8 ;creates the file
mov EBX, filename
mov ECX, 644O ;octal instruction
int 80h ;kernel interrupt
cmp EAX,0 ;throws error if something is amiss
jbe error
mov [file_descriptor],EAX
mov ECX,[number_of_bases]
;-------------------------------------------------------------
;randomization of base numbers
writing_loop:
rdtsc
mov EAX, EDX
mov EDX, 0
div ECX
mov EDX, 0
mov EBX, 4
div EBX
mov [random_number], EDX
mov EDX, 0
mov EAX,[random_number]
cmp EAX,0
je assignment_A
cmp EAX,1
je assignment_C
cmp EAX,2
je assignment_G
cmp EAX,3
je assignment_T
join_char:
mov [base + EBX],EBX
loop writing_loop
PutStr base
.EXIT
;------------------------------------------------------------
;file generation error message
error:
PutStr error_msg
jmp ask_details
;------------------------------------------------------------
;assignments
assignment_A:
mov EBX, [base_A]
jmp join_char
assignment_C:
mov EBX, [base_C]
jmp join_char
assignment_T:
mov EBX, [base_T]
jmp join_char
assignment_G:
mov EBX, [base_G]
jmp join_char
First it compares some random numbers I obtained with rdtsc, depending on what comes up, it will assign a letter to EBX this letter(base_A,base_C,base_T or base_G) is then supposed to go into base. I tried using
mov [base + EBX],EBX but that just printed an empty space, I used this because it seemed to work in the examples I looked at, but I'm not really sure how concatenating works in NASM. I don't know if anyone knows any simple methods to concatenate those characters together, if it is possible. This is really minor, so I'm hoping I don't have to add a lot of code, the only thing I need this string for is to write it in a file later. I would do that without the string but I need all my registers to write to the file so I can't do it letter by letter.
EDIT: What I need to know how to do is how to join each letter once it has been picked. Base is empty for example, then after a letter is picked, it gets thrown in there, however after the loop runs again, another letter will be picked, and I need to add it to base after all that's done.
I am trying to write a program using x86 assembly that can search for a word in a text. When the word is present in the text, the program will inform the user. I'm still having a problem in comparing the strings. Any advice?
.model small
.stack 200h
.data
message1 db "Enter your text here: $"
text db 150,151 dup(0)
message2 db 10,13,"Enter the word that you want to find: $"
find db 20,21 dup(0)
yesmessage db 10,13,"The word is in the text$"
nomessage db 10,13,"Sorry the word is not in the text$"
.code
Start:
;Display message and key in strings
mov ax,seg message1
mov ds,ax
mov si,offset text
mov di,offset find
mov dx,offset message1
mov ah,09h
int 21h
mov dx,si
mov ah,0Ah
int 21h
mov ax,seg message2
mov ds,ax
mov dx,offset message2
mov ah,09h
int 21h
mov dx,di
mov ah,0Ah
int 21h
;compare strings
mov bx,00
mov bl,text+1
mov bh,find+1
cmp bl,bh
jne L1
add si,2
add di,2
L2:mov bl,byte ptr[si]
cmp byte ptr[di],bl
jne L1
inc si
inc di
cmp byte ptr[di],"$"
jne L2
mov ah,09h
mov dx,offset yesmessage
int 21h
L1:mov ah,09h
mov dx,offset nomessage
int 21H
mov ax,4c00h
int 21h
end start
the expected result should be:
Example 1:
Enter your text here: He is old
Enter the word that you want to find: old
The word is in the text
Example 2:
Enter your text here: He is old
Enter the word that you want to find: young
Sorry the word is not in the text
I can see a couple of obvious problems in your code. See my comments below:
mov bx,00 ; this instruction is redundant
mov bl,text+1
mov bh,find+1
cmp bl,bh
jne L1 ; it's quite likely that the strings won't have the same length,
; i.e. that find will be shorter than text. this condition is
; therefore incorrect. it would make more sense to use jl, i.e.
; jumping to the negative print if text is shorter than find.
mov ah,09h
mov dx,offset yesmessage
int 21h
L1:mov ah,09h
mov dx,offset nomessage ; you'll be printing both messages in cases where
int 21H ; the substring is found, because you don't have
; any jump that skips past it.