linux nasm move a value in AL up to AX
Just clear the ah
register instead. The ax
register consists of it's high and low part - ah:al
The same applies to bx
(bh,bl) cx
(ch,cl) and dx
(dh,dl) registers
NASM adding value to register bug
I have an idea - I'm not sure if it is correct:
In your program you call "open" two times. One time you commented out the mov ecx, ...
; the other time the ecx
register has never been set at all:
openFileIn:
mov eax, 5
mov ebx, fileName
; <-- Here you are trusting Linux that ecx=0 on program start
; This is not guaranteed;
; it may change in future Linux versions!
mov edx, 0777
int 0x80
mov [fd_in], eax
ret
openFileOut:
mov eax, 5
mov ebx, outName
;mov ecx, 1 <-- why did you comment this out?
; Maybe "1" is not the correct value!
mov edx, 0777
int 0x80
In anoter line you write some address to the ecx
register:
readFromFileIn:
mov eax, 3
mov ebx, [fd_in]
mov ecx, info ; <-- Here
mov edx, IMAGE_SIZE
int 0x80
ret
When you add instructions to your code the addresses of elements in the program may change - including the address of info
.
I suspect that without the additional instruction the address of info
is a valid parameter for the "open" system call by chance while after inserting the instruction the address is no longer a valid parameter for "open".
You could test this by running both variants of the program with the strace
tool which shows you which system calls are called with wich parameters.
How can i copy an array in nasm x86 assembly for Linux, porting 16-bit DOS code?
The final code in nasm is this
section .text
global _start
cpu 386
_start:
MOV ESI, TABLE_A
MOV EDI, TABLE_B
MOV CX, 3
COPY_LOOP:
MOV AL, [ESI]
MOV [EDI], AL
INC SI
INC DI
LOOP COPY_LOOP
MOV AX,1
INT 80h
section .data
TABLE_A DB 10, 5, 1
TABLE_B DB 0, 0, 0
Move character from a string to a register in Assembly
The instruction mov al, msg2
would have gotten you the first byte of the string if this were MASM, but since you're using NASM you need to write the square brackets whenever you want to address memory.
mov al, [msg2]
When you wrote mov byte al, msg2
, you asked NASM to put the address of msg2 in the AL
register which is nearly always wrong since an offset address is supposed to be 16-bit! This is why you received the error:
obj output driver does not support one-byte relocations
Since your aim seems to be to get, one after the other, each character of the string, an instruction that just gets the first character can't help you very much. You need to put the address of the string in a register, read the memory where that register points at, and then increment the register. After doing something useful with AL
, you test if the register points behind the last character of the string and if it doesn't you jump back to read the next character.
mov bx, msg2
Next:
mov al, [bx]
inc bx
...
cmp bx, msg2 + 10 ;Only if msg2 has precisely 10 characters
jb Next
A loop like this can only work if whatever code you replace the ... with, doesn't clobber the loop control register BX
. If need be you can preserve BX
yourself by adding push
and pop
instructions:
mov bx, msg2
Next:
mov al, [bx]
inc bx
push bx
...
pop bx
cmp bx, msg2 + 10 ;Only if msg2 has precisely 10 characters
jb Next
NASM Assembly - Get the Result of Multiplying Two Numbers in a Loop
This is an update, I fixed it. :)
;nasm 2.13.02
section .bss
result: resb 2
num1: resb 2
num2: resb 2
quotient: resb 2
remainder: resb 2
section .text
global _start
_start:
; setup registers
; mul -> AX = (AX * BX = DX BX)
;The multiplicand should be in the AX register,
;and the multiplier is a word in memory or another register.
;For example, for an instruction like MUL DX,
;you must store the multiplier in DX and the multiplicand in AX.
;The resultant product is a doubleword, which will need
;two registers. The high-order (leftmost) portion gets stored
;in DX and the lower-order (rightmost) portion gets stored
;in AX.
mov [num1], word 0x2A ;store 42 in eax
mov [num2], word 0x2B ;store 43 in edx (42*43=1806)
mov ax, [num1]
mov bx, [num2]
mul bx
mov [result], ax
call convert_values
;----------------------------------
; divide by ten
; div -> AX = (AX(dividendo) / BL(divisor) = AL (Quotient) AH (Remainder))
;The dividend is assumed to be in the AX register (16 bits).
;After division, the quotient goes to the AL register and
;the remainder goes to the AH register.
convert_values:
xor ax, ax ; clears AX register to `0`
mov ax, [result]
mov bl, 10 ; 10
div bl ; divide por 10
mov [quotient], al ; save the Quotient
call print_char ;print the latest character
mov ax, [quotient] ;move `Quotient` to AX register
test ax,ax ;Compares if AX register is equal to `0`
jz exit; ;if flag `ZF` is equal to `1` jump to `exit` label
mov [result], ax ;moves data from AX register to `result`
cmp ax,0 ;set flags based on ax value
jnz convert_values ;while al != 0 continue process
ret
; print a character
print_char:
mov [remainder], ah ; gets the Remainder
add [remainder], word '0'
mov eax,4 ; The system call for write (sys_write)
mov ebx,1 ; File descriptor 1 - standard output
mov ecx,remainder ; Put the offset of hello in ecx
mov edx,1 ; is a constant, so we don't need to say
int 80h ; Call the kernel
ret
;---------------------------------------------
exit:
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return code of 0 (no error)
int 80h;
Unexpected results from division depending on whether I use EAX, AX, or AL
In this part of the code:
46 sub byte [esi], 48 ; get value of digit
47 add edi, [esi] ; add to summ
It looks like the intent is to add a single digit to the sum, but that is not what actually happens. add edi, [esi]
is implicitly the same thing as add edi, dword [esi]
, so really 4 characters are being added to the sum in an interesting way, though only the bottom one is intended, and only one of them is adjusted from an ASCII char to its numeric equivalent (by the way I don't quite understand why you change them back to ASCII characters, but that should be fine in principle, just redundant).
Using only the low byte of the result works, because the low byte is never "polluted" that way, the extraneous characters are added into the high bytes of eax
.
How to fix: make sure you add only one char at the time. For example
movzx eax, byte [esi]
sub eax, 48
add edi, eax
If you prefer, you can merge the sub
and add
into lea
:
movzx eax, byte [esi]
lea edi, [edi + eax - 48]
x86 nasm assembly, how to print multiplication result correctly?
The AAM
instruction could be useful for cases where the result would have at most 2 digits. In your case 12 x 12 = 144, so that's a no-go.
The conversion loop that you use is almost correct, but you are mixing sizes in relation to the DIV
instruction. If you give a byte-sized operand to DIV
then the operation will divide AX
by that byte and the remainder will be in AH
. If you give a word-sized operand to DIV
then the operation will divide DX:AX
by that word and the remainder will be in DX
.
Because you're writing 32-bit code, better also write the conversion using 32-bit registers.
Instead of using a digits counter, use a sentinel on the stack. No need to preserve ECX
while displaying.
The display function expects a pointer in ECX
. Just use the stackpointer for this and pop the value post-printing.
mov al, 12
mov bl, 12
mul bl ; answer in AX
movzx eax, ax
mov ebx, 10 ; Divisor constant
push ebx ; Sentinel
.a: xor edx, edx
div ebx ; Divide EDX:EAX with EBX, quotient EAX, remainder EDX
add edx, '0' ; Add '0' to make it into character
push edx
test eax, eax ; If EAX (the quotient) is not zero, loop again.
jnz .a
.b: mov eax, 4
mov ebx, 1
mov ecx, esp
mov edx, 1
int 0x80
pop eax
cmp dword [esp], 10 ; Is it the sentinel ?
jne .b ; No, it's a digit
pop eax ; Remove sentinel
Although not 32-code, Displaying numbers with DOS has more info about converting numbers into text.
How to mov values in eax register, ah and al left by 2 bytes? x86 Assembly
If you can't use shl eax, 16
like a normal person, your other options include the following:
add eax,eax
repeated 16 times (yuck, slow), in a loop partially unrolled, or fully unrolled.- store / reload at an offset: also slow, but only for latency (store-forwarding stall). Throughput can be ok, while latency is pretty close to the same 16 cycles as the 16x
add
way on a typical modern x86.
sub esp, 16 ; reserve some stack space.
...
mov [esp+2], ax ; 2 byte store
mov eax, [esp] ; 4-byte reload with previous AX in the top half
mov ah, ... ; overwrite whatever garbage in the low 2 bytes
mov al, ...
x86 is little-endian, so load/store of EAX to addr
loads/stores AL to that same addr
, and AH to addr+1
., with the high 2 bytes coming from addr+2 and +3.
Reading EAX after writing AH and AL will also force the CPU to merge partial registers if it renamed AH (and maybe AL) separately from the full EAX, but clearly if you're restricting yourself to only a tiny subset of the ISA then high performance isn't your top goal. (See Why doesn't GCC use partial registers? and How exactly do partial registers on Haswell/Skylake perform? Writing AL seems to have a false dependency on RAX, and AH is inconsistent for more details.)
For the store-forwarding stall part, see Can modern x86 implementations store-forward from more than one prior store?
Depending how much you're doing with the new low part (the new AH and AL), you might actually do them in a separate register (like DH and DL), so out-of-order exec can get started on that work, without a false dependency on the store-forwarding reload, especially on CPUs that don't rename AL (or even AH) separately from EAX. (i.e. CPUs that aren't Intel P6 family, like crusty old Nehalem).
So you'd do
mov [esp+2], ax ; 2 byte store
mov eax, [esp] ; 4-byte reload with previous AX in the top half
mov dl, ...
mov dh, ...
... more computation with these two
mov ax, dx ; replace low 2 bytes of EAX
mov ax,dx
might need to wait for the old EAX value to be "ready", i.e. for the reload to complete, so it can merge into it as part of running that instruction. (On Intel Sandybridge-family, and on all non-Intel CPUs.) So this lets the computations on DL/DH overlap with the store-forwarding latency.
Just to be clear, all this discussion about tradeoffs is about performance, not correctness; all ways I've shown here are fully correct. (unless I made a mistake :P)
Assembly, NASM; how is the information in 32 bit registers divided among sub registers?
AL will have the first t, AH will have e, AX will have et (te depending on how you consider the lower character and higher character). It's been likely 15-18 years since I've touched assembler, but that's what I remember anyhow.
szString will look like this in memory:
t e s t
0x74 0x65 0x73 0x74
mov eax,[szString]
will have:
AL - 0x74
AH - 0x65
AX - 0x6574
EAX - 0x74736574
Primitive ASCII art:
[74][65][73][74]
[-----EAX------]
[--AX--]
[AL][AH]
Related Topics
Gradle 1.3: Build.Gradle Not Building Classes
File Listed Twice in Rpm Spec File
Placement of '-L' Option in Gcc
Linux Device Driver File Operations: It Is Possible to Have Race Conditions
Linux/Glibc. How to Use Fprintf in Signal Handler
How Does/Frequent Unix Tee Command Write Stdout Terminal Output to File? If The Output Is Too Big
Is It Efficient to Use Epoll with Devices (/Dev/Event/...)
How to Delete X Number of Files in a Directory
Path Environment Variable in Linux
Is There Compatible Odbc Driver with Mariadb 10 on Linux
Azure Cli Aks Install Cli Permission Denied and Sudo Does Not Work
Julia: System Image File "Sys.Ji" Not Found
Why Sigint Can Stop Bash in Terminal But Not via Kill -Int
Unix Command to Convert Xls File into Xlsx File
How to Show Printk() Message in Console
How to Solve Ssh: /Usr/Lib64/Libcrypto.So.10: No Version Information Available