When I run this program it says:
jdoodle.asm:9: error: invalid combination of opcode and operands
The problem is the AND al, ah. The rest of the code should be correct, I just need to know how to solve this problem because as it seems I can't do an AND between 2 registers.
section .text
global _start
_start:
call _input
mov al, input
mov ah, maschera
and al, ah
mov input, al
call _output
jmp _exit
_input:
mov eax, 3
mov ebx, 0
mov ecx, input
mov edx, 1
int 80h
ret
_output:
mov eax, 4
mov ebx, 1
mov ecx, input
mov edx, 1
int 80h
ret
_exit:
mov eax, 1
int 80h
section .data
maschera: db 11111111b
segment .bss
input resb 1
MASM/TASM/JWASM syntax is different from NASM. If you want to load/store data at an address you need to explicitly use square brackets. If you want to use the MOV instruction to place the address of a label in a variable you do not use square brackets. Square brackets are like a de-reference operator.
In 32-bit code you will want to ensure addresses are loaded into 32-bit registers. Any address above 255 won't fit in an 8 byte register, any address above 65535 won't fit in a 16-bit register.
The code you were probably looking for is:
section .text
global _start
_start:
call _input
mov al, [input]
mov ah, [maschera]
and al, ah
mov [input], al
call _output
jmp _exit
_input:
mov eax, 3
mov ebx, 0
mov ecx, input
mov edx, 1
int 80h
ret
_output:
mov eax, 4
mov ebx, 1
mov ecx, input
mov edx, 1
int 80h
ret
_exit:
mov eax, 1
int 80h
section .data
maschera: db 11111111b
segment .bss
input resb 1
Related
I am new have very small problem with assembly NASM in linux. I made simple program for practice that when you put in the text, it adds simple decoration in form of stars. The expected output is:
*********EXAMPLE*********
instead:
*********EXAMPLE
*********
here is the complete code of the program (long) i have use edb to check the code and check EDX register if it match the len take by the null byte check to print correct number of characters.
section .data
prompt db "Please enter a word (MAX: 10 Characters) : ", 0xa, 0xd
plen equ $ - prompt
stars times 9 db "*"
section .bss
text resb 10
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, prompt
mov edx, plen
int 0x80
mov eax, 3
mov ebx, 0
mov ecx, text
mov edx, 11
int 0x80
xor ecx, ecx
mov esi, text
mov ecx, 0
loop1:
inc ecx
cmp byte [esi + ecx], 0x00
jne loop1
push ecx
jmp printexit
printexit:
mov eax, 4
mov ebx, 1
mov ecx, stars
mov edx, 9
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, text
pop edx
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, stars
mov edx, 9
int 0x80
mov eax, 1
int 0x80
I'm trying to make a very simple assembly program run, however I seem to get segfaults whatever I do.
Here is my code (should print 'a' on a linux machine)
section .data
buffer times 50 db 97
pointer db 0
section .text
global _start
_start:
mov ECX , pointer
mov EDX , [buffer + ECX]
mov EAX , 4
mov EBX , 1
mov ECX , EDX
mov EDX , 1
int 0x80
It causes a segfault on the first MOV but it seems obvious to me that it should work.
I reduced it to almost nothing and it still segfault.
section .data
msg db "hello"
section .text
global _start
_start:
mov EAX,1
I've run this succesfully:
section .text
global _start
_start:
mov ax, 0b
dec ax
sub ax, 11111111b
mov bx, 97
add ax, bx
mov [INVENTORY], ax ; put a in first inventory pos
mov eax, 4
mov ebx, 1
mov ecx, INVENTORY
mov edx, 1
int 0x80
mov ax, [INVENTORY]
add ax, 1
mov [INVENTORY + 1], ax ; put b in second inventory pos
mov [VAR], ax
mov eax, 4
mov ebx, 1
mov ecx, VAR
mov edx, 1
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, '\n'
mov edx, 1
int 0x80
mov eax,1
int 0x80
_newline:
section .data
VAR DW 0
INVENTORY TIMES 8 DW 0
Is it possible that it has to do with the symbols I use for newlines or tabs? I generate the assembly from java and I use \t for tabs and \n for new lines (and spaces so it doesn't look too bad.
I'm using NASM and I'm running it here:
https://www.tutorialspoint.com/compile_assembly_online.php
Thank you!
If you are just trying to print out a set of 'a's.
section .data
buffer times 50 db 97
len.buffer equ $-buffer
pointer db 0
section .text
global _start
_start:
; ssize_t write(int fd, const void *buf, size_t count);
; i386 ebx ecx edx esi edi ebp
mov EAX , 4 ; write syscall
mov EBX , 1 ; std out
lea ecx, [buffer] ; buffer
mov edx, len.buffer ; size
int 0x80
_exit:
mov eax, 1 ; exit syscall
int 0x80
output:
./yvon_001
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ndavid#ubuntuserver00A:~/asm$ ./yvon_001
In the end #MichealPetch was right, I needed to add an EXIT syscall at the end of the code. The sample I tried still did a SEGFAULT because I was moving pointer instead of [pointer] in a registry.
Thanks for comments and answers!
I try write follow code, use int 0x80 to print number 5 but it don't print anything.
segment .bss
num1 resb 1
section .text
global _start
_start:
mov dword [num1],5
add [num1],byte '0'
mov ecx, dword [num1]
mov eax, 4
mov ebx, 1
mov edx, 1
int 0x80
mov eax, 1
int 0x80
System call 4 expects ecx to contain a pointer to a NUL-terminated string.
So instead of mov ecx, dword [num1] you should use mov ecx, num1.
I'm trying to print Hi 10 times. This is my code.
section .data
msg db "Hi"
section .text
global _start
_start:
mov cx, 10
L1:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, 3
int 0x80
dec cx
jnz L1
mov eax, 1
mov ebx, 0
int 0x80
gdb reports that mov edx, 3 overwrites the cx register to some crazy value and so the loop keeps going forever.
What am i doing wrong? Is it because they are the same register?
How does one program in assembly with so few registers?
Compiling on centos with nasm and ld
Thanks
You're looking at the wrong line. The problem is "mov ecx, msg". ECX is the extended register of which CX is the lower part, so you're writing over it.
It's best to save your loop counter on the stack, because who knows that the 'int' call might change. Add 'push cx' (or ecx) after 'L1:'. and 'pop cx' after the 'int' call to preserve the contents of the register.
This code fixes it:
section .data
msg db "Hi"
counter dw 10
section .text
global _start
_start:
L1:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, 2
int 0x80
mov cx, [counter]
dec cx
mov [counter], cx
jnz L1
mov eax, 1
mov ebx, 0
int 0x80
move the value into a variable and then dec it then put it back
Currently I'm trying to loop over every single byte in a buffer (read from a file) and compare it to see if any of them is a whitespace, and write them to STDOUT. For some reason the program compiles and runs fine, but produces zero output.
section .data
bufsize dw 1024
section .bss
buf resb 1024
section .text
global _start
_start:
; open the file provided form cli in read mode
mov edi, 0
pop ebx
pop ebx
pop ebx
mov eax, 5
mov ecx, 0
int 80h
; write the contents in to the buffer 'buf'
mov eax, 3
mov ebx, eax
mov ecx, buf
mov edx, bufsize
int 80h
; write the value at buf+edi to STDOUT
mov eax, 4
mov ebx, 1
mov ecx, [buf+edi]
mov edx, 1
int 80h
; if not equal to whitespace, jump to the loop
cmp byte [buf+edi], 0x20
jne loop
loop:
; increment the loop counter
add edi, 1
mov eax, 4
mov ebx, 1
mov ecx, [buf+edi]
int 80h
; compare the value at buf+edi with the HEX for whitespace
cmp byte [buf+edi], 0x20
jne loop
; exit the program
mov eax, 1
mov ebx, 0
int 80h
The main problem was that I didn't given the address of bufsize ([bufsize]), also the loops had some problems.
Here's the fixed version, thanks everyone for your input.
section .data
bufsize dd 1024
section .bss
buf: resb 1024
section .text
global _start
_start:
; open the file provided form cli in read mode
mov edi, 0
pop ebx
pop ebx
pop ebx
mov eax, 5
mov ecx, 0
int 80h
; write the contents in to the buffer 'buf'
mov eax, 3
mov ebx, eax
mov ecx, buf
mov edx, [bufsize]
int 80h
; write the value at buf+edi to STDOUT
; if equal to whitespace, done
loop:
cmp byte [buf+edi], 0x20
je done
mov eax, 4
mov ebx, 1
lea ecx, [buf+edi]
mov edx, 1
int 80h
; increment the loop counter
add edi, 1
jmp loop
done:
; exit the program
mov eax, 1
mov ebx, 0
int 80h