nasm报错:operator may only be applied to scalar values

  搜到了一篇不错的帖子:

  (回答的那个人实在是太敬业了)


Hey all.

I'm a complete beginner in assembly and have chosen NASM to work my way up with. But I have a problem with the pseudo-instruction set. More precisely, I don't understand how the expressions "$ and $$" are used in correlation with times.

It's no problem for me to understand what "times" does, but I do not understand the expressions used together with times.

Like;

times 512-($-$$) db 0

It is explained what it does (in the tutorial), but not how it is done.

My questions according to this example;
1. Why is there a dash ("-") after 512 and before "(" ?
2. Can someone elaborate what $ means and is used for?
3. Can someone elaborate waht $$ means and is used for?

I read the 2 lines of description about $ and $$ multiple times now, and I still don't understand what they are. Can someone help?


下面是回答:
The mysterious '-' is a minus sign. That takes care of that part. :)

Nasm uses '$' for several purposes, in this case it's "here" - the current assembly location. Actually, the location at the beginning of the line.

'$$' is the beginning of the current section.

You might reasonably think that '$' would be enough, but '$', like any symbol, is a "relocatable value". That is, the linker and loader can alter this value in ways Nasm knows nothing about. In the specific case of "-f bin" output, Nasm acts as its own linker, but that happens in the "output driver", and we need to know this value in the actual "assemble" routine, which runs first. This is what Nasm means when it says "not a scalar value". It's a vector??? No, it's a "relocatable value".

In some cases, a relocatable value is okay...

Code: [Select]
mov eax, $

Nasm doesn't need to know the value at "assemble-time", it codes "mov eax, (this label)", and the linker/loader will fill in the relocated value. But:

Code: [Select]
mov eax, $ << 1

... now we're asking Nasm to do an assemble-time calculation on a value it doesn't know, so it whines.

The difference between two labels (in the same section!) is a "scalar value". The linker/loader can change the two values, but the distance between them remains the same. Therefore, we can do a calculation on it - and it's an acceptable argument to "times".

Code: [Select]
org 0 ; the default, if no origin specified
section .text ; the default, if no section specified

nop
nop
nop ; three bytes of "code"

times 512 - ($ - $$) db 0

In this case, '$' is 3 and '$$' is 0, so we're emitting 509 zeros to bring the total file size to 512 bytes. In this case, just '$' would have worked, if Nasm would accept it, which it won't.

Code: [Select]
org 7C00h
section .text

nop
nop
nop ; three bytes of "code"

times 512 - ($ - $$) db 0

Now, '$' is 7C03h and '$$' is 7C00h. We're still adding 509 zeros to pad to 512 bytes, but in this case '$' by itself would *not* do what you want!

The expression "512 - ($ - $$)" can be written without the parentheses as "512 + $$ - $", but this is even less clear (IMHO). In a bootsector, 510 is more common than 512, since we want the two byte "boot signature" after it, and the entire bootsector needs to be 512 bytes, but that doesn't alter '$' and '$$'...

Does that make you less confused, or more? :)

Best,
Frank

 

 

 

posted on 2012-08-25 23:16  weiweishuo  阅读(484)  评论(0编辑  收藏  举报

导航