问题
i have an assignment that asks to define 4 integers, each of a different byte length (1, 2, 4, 8)
would this code work?
segment .data
one db 1
two dw 01
four dd 1011
eight dq 01101110
global _start
_start:
mov rax, [one] ;
mov rbx, [two] ;
im also curious if i can safely store these values into registers to be used for addition in the future. I'm supposed to use sign extension for the shorter values, but could use some direction
回答1:
You're writing constants in decimal. If you want the digits to be interpreted as base-2, you need to tell the assembler about it. It's not going to do that just because they happen to all be 0 or 1.
3.4.1 Numeric Constants in the NASM online manual (first google hit for: nasm binary constant):
Some examples (all producing exactly the same code):
mov ax,200 ; decimal
mov ax,0200 ; still decimal
mov ax,0200d ; explicitly decimal
mov ax,0d200 ; also decimal
mov ax,0c8h ; hex
mov ax,$0c8 ; hex again: the 0 is required
mov ax,0xc8 ; hex yet again
mov ax,0hc8 ; still hex
mov ax,310q ; octal
mov ax,310o ; octal again
mov ax,0o310 ; octal yet again
mov ax,0q310 ; octal yet again
mov ax,11001000b ; binary
mov ax,1100_1000b ; same binary constant
mov ax,1100_1000y ; same binary constant once more
mov ax,0b1100_1000 ; same binary constant yet again
mov ax,0y1100_1000 ; same binary constant yet again
Obviously you can use these prefixes or suffixes on constants anywhere, not just immediate operands.
So yes, you can use binary. Note that the code in your question used a one-bit constant, not a one-byte constant, for the value stored in one
. one = 1
, and two = 2
, but four = 2^3 + 0 + 2^1 + 1 = 11(decimal)
.
eight
is similarly strangely defined. It should be eight = 1000b
.
All power-of-two integers only have a single bit set in their binary representation, just like all power-of-10 numbers have a single 1
in their decimal representation.
Maybe those names were just the widths, not the values?
mov rax, [one]
is an 8-byte load, spanning the db
, dw
, and dd
, and the first byte of the dq
.
The only form of the mov instruction that does any sign-extension is mov r64, imm32
, and that sign-extends the immediate, not a memory source. Both operands for mov
are always the same size (except for the imm32 case); it unfortunately doesn't even have a sign-extended imm8 form like add r/m64, imm8
does.
If you want to load from memory with sign-extension, look up movsx in the insn ref manual. (linked from the x86 info wiki.) e.g. movsx rax, byte [mem]
. In your case, zero-extending would give the same result: movzx eax, byte [one]
to zero-extend into RAX. (Generally prefer zero-extension; on some CPUs it's slightly more efficient.)
(Also, you normally want default rel
so [one]
is a RIP-relative addressing mode.)
来源:https://stackoverflow.com/questions/34057237/can-i-use-binary-to-write-integer-constants-in-assembly