Chinaunix

标题: 什么叫非显式的整型立即数 [打印本页]

作者: zylthinking    时间: 2012-10-15 11:32
标题: 什么叫非显式的整型立即数


如上高亮文字, 什么立即数是 not an explicit integer ???
作者: goldenfort    时间: 2012-10-15 11:43
回复 1# zylthinking


    我理解,就是不是 编译 在 代码段中的 固定数字, 而是 在 堆栈 和数据段中的 整型数, 可以不是明确定义为整型数的, 可以通过类型转换
作者: zylthinking    时间: 2012-10-15 11:45
goldenfort 发表于 2012-10-15 11:43
回复 1# zylthinking


具体汇编代码长什么样子的?

作者: folklore    时间: 2012-10-15 11:45
int i=10;
op (i);

??

作者: folklore    时间: 2012-10-15 11:46
这东西没有更详细的上下文,猜不出来吧。
作者: zylthinking    时间: 2012-10-15 11:46
folklore 发表于 2012-10-15 11:45
int i=10;
op (i);


这不就是一个变量嘛
作者: goldenfort    时间: 2012-10-15 11:48
回复 3# zylthinking


    就是  move 一个 地址 到register 。
   所有变量都有地址, 立即数 没有地址
作者: zylthinking    时间: 2012-10-15 11:50
folklore 发表于 2012-10-15 11:46
这东西没有更详细的上下文,猜不出来吧。


上下文就是, 什么情况下可以写这样的语句

int result;
asm ("mov %1 %0" : "=r"(result) : "s" (????????))

???? 应该填什么样的东西, 这个东西是 “An immediate integer operand whose value is not an explicit integer”
作者: zylthinking    时间: 2012-10-15 11:53
goldenfort 发表于 2012-10-15 11:48
回复 3# zylthinking

不明白啥意思
作者: folklore    时间: 2012-10-15 11:56
看了楼主的英文,大意是说:
如果指令
ins n
是,n的值容许在编译器未知(也就是只有Run-time时才可知,即可被计算),则该指令必然要允许n为任意可能的整数。

这句话在说:
ins n 中的n是非立即数,也就是变量的情况。

ins 4      <--使用立即数

mov 4,n
ins n      <-- 使用非立即数,也就是非显式的立即数

只能猜到这些,为什么不直接说: 间接操作数,而用"非显式的整数立即数",则不知道
作者: zylthinking    时间: 2012-10-15 11:59
本帖最后由 zylthinking 于 2012-10-15 12:02 编辑
folklore 发表于 2012-10-15 11:56
看了楼主的英文,大意是说:
如果指令
ins n

insn 是英文指令的意思, 是英文单词, 没有说 ins 是指令,  n 是操作数
作者: folklore    时间: 2012-10-15 12:13
回复 6# zylthinking


    是,但是事实上是常数

作者: folklore    时间: 2012-10-15 12:17
回复 8# zylthinking


    asm ("mov %1 %0" : "=r"(result) : "s" (????????))

mov result,????
????要填常数

所以,你给出的 ???????? 必须是常数表达式,也就是 1+1

const int n=10;
    asm ("mov %1 %0" : "=r"(result) : "s" (n+1))

这类东西。

作者: zylthinking    时间: 2012-10-15 12:19
folklore 发表于 2012-10-15 12:17
回复 8# zylthinking
  1.     const int nn=10;
  2.     int result;
  3.     asm ("mov %1 %0" : "=r"(result) : "s" (nn+1));
  4.    
复制代码
fatal error: error in backend: Invalid operand for inline asm constraint 's'!

作者: zylthinking    时间: 2012-10-15 12:20
goldenfort 发表于 2012-10-15 11:48
回复 3# zylthinking
  1.     const int nn=10;
  2.     int result;
  3.     asm ("mov %1 %0" : "=r"(result) : "s" (&nn));
复制代码
fatal error: error in backend: Invalid operand for inline asm constraint 's'!
作者: folklore    时间: 2012-10-15 12:20
回复 11# zylthinking


没见过,学习了。   
作者: folklore    时间: 2012-10-15 12:23
回复 14# zylthinking


    也就是编译器不认为const int n=0;中的n是常量(这是正确的)

1+1可以吧。
作者: folklore    时间: 2012-10-15 12:24
回复 15# zylthinking


    int n;
  &n <<不是常量,要Run-time计算的。

这里要求常量表达式。
作者: zylthinking    时间: 2012-10-15 12:36
folklore 发表于 2012-10-15 12:24
回复 15# zylthinking


你说怎么写就行了
作者: sonicling    时间: 2012-10-15 13:07
楼主真是的,也不贴全,后面不是说明原因了吗。

‘s’
An immediate integer operand whose value is not an explicit integer is allowed.
This might appear strange; if an insn allows a constant operand with a value
not known at compile time, it certainly must allow any known value. So why
use ‘s’ instead of ‘i’? Sometimes it allows better code to be generated.

For example, on the 68000 in a fullword instruction it is possible to use an
immediate operand; but if the immediate value is between −128 and 127, better
code results from loading the value into a register and using the register. This
is because the load into the register can be done with a ‘moveq’ instruction. We
arrange for this to happen by defining the letter ‘K’ to mean “any integer outside
the range −128 to 127”, and then specifying ‘Ks’ in the operand constraints.

‘I’, ‘J’, ‘K’, . . . ‘P’
Other letters in the range ‘I’ through ‘P’ may be defined in a machine-dependent
fashion to permit immediate integer operands with explicit integer values in
specified ranges. For example, on the 68000, ‘I’ is defined to stand for the
range of values 1 to 8. This is the range permitted as a shift count in the shift
instructions.

作者: sonicling    时间: 2012-10-15 13:12
按照for example的说法,s后面仍然需要是个立即数,但是gcc有可能会把这个立即数放到寄存器里面,因为RISC的指令支持的立即数长度可能不够,你的立即数在指令里放不下。

作者: zylthinking    时间: 2012-10-15 13:44
sonicling 发表于 2012-10-15 13:12
按照for example的说法,s后面仍然需要是个立即数,但是gcc有可能会把这个立即数放到寄存器里面,因为RISC的 ...


我觉得未必这样理解啊, 照这样理解, 那么 编译时未知 该怎么解释, 还有他说s 代替 i 是因为可以产生更佳的代码, 那就是说 i 也行了, 但如果说是s长度不够, i 就够了????
而且, 似乎将-128 - 127 放进寄存器是 K 的功劳, s 应该依旧在强调这是一个编译时未知值。
似乎这个例子也有些难理解, 照他的说法,  K 应该是表示的是排除 -128 - 127 的范围的值的,  Ks 就字面意思, 操作数应该是一个 [min, -128] || [128, max] 范围内的值, 并且是编译时不可知的; 那怎么达到如果是 -128 -- 127 就能放进寄存器的目的的----输入压根就不在这个范围啊
作者: zylthinking    时间: 2012-10-15 14:17
sonicling 发表于 2012-10-15 13:12
按照for example的说法,s后面仍然需要是个立即数,但是gcc有可能会把这个立即数放到寄存器里面,因为RISC的 ...
  1. int main(int argc, char** argv){
  2.     int result = 10;
  3.     const int n = 0;
  4.     __asm__ (
  5.             "movl %1, %0\n"
  6.             :"=r"(result)
  7.             :"s"(9)
  8.     );

  9.     printf("%d\n", result);
  10.     return 0;
  11. }
复制代码
$> cc -m32 a.c --std=c99
cc1: error in backend: Invalid operand for inline asm constraint 's'!
作者: folklore    时间: 2012-10-15 14:43
回复 23# zylthinking


    你用的 arm? 不熟,但这都不行,我怀疑 ARM不支持立即数到内存

改为:

asm ("mov %1 ,%r0; mov %r0,%0" : "=r"(result) : "s" (????????));

试试
作者: zylthinking    时间: 2012-10-15 14:43
folklore 发表于 2012-10-15 14:43
回复 23# zylthinking


x86 都不行
作者: sonicling    时间: 2012-10-15 15:51
回复 23# zylthinking
  1.         case 's':
  2.           if (CONST_INT_P (op)
  3.               || (GET_CODE (op) == CONST_DOUBLE
  4.                   && GET_MODE (op) == VOIDmode))
  5.             break;
  6.           /* Fall through.  */

  7.         case 'i':
  8.           if (CONSTANT_P (op) && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)))
  9.             result = 1;
  10.           break;
复制代码
这是gcc asm_operand_ok()的部分代码,"s"检查通过的条件是

!CONST_INT_P (op) &&
((GET_CODE (op) != CONST_DOUBLE || GET_MODE (op) != VOIDmode)) &&
CONSTANT_P(op) &&
...

也就是说"s"不能是常量整型或者常量浮点,但必须是常量对象,符合这种条件的对象有
const_vector
const // 常量表达式
label_ref // asm label
symbol_ref // named label
作者: zylthinking    时间: 2012-10-15 15:58
本帖最后由 zylthinking 于 2012-10-15 15:59 编辑
sonicling 发表于 2012-10-15 15:51
回复 23# zylthinking 这是gcc asm_operand_ok()的部分代码,"s"检查通过的条件是

!CONST_INT_P (op) && ...


const_vector
const // 常量表达式
label_ref // asm label
symbol_ref // named label

这些东西各是什么??? 真的没概念
就常量表达式而言, 我胡试了几个, 似乎都不行

    __asm__ (
        "movl %1, %0\n"
        :"=r"(result)
        :"s"(sizeof(double))
    );

    __asm__ (
        "movl %1, %0\n"
        :"=r"(result)
        :"s"(1 + 1)
    );

LABEL:
    __asm__ (
        "0:"
        "movl %1, %0\n"
        :"=r"(result)
        :"s"(0b)
    );
   
LABEL:
    __asm__ (
        "movl %1, %0\n"
        :"=r"(result)
        :"s"(LABEL)
    );
   
作者: zylthinking    时间: 2012-10-15 16:01
这也不行:

int test(){
    return 0;
}

int main (int argc, const char * argv[])
{

    int result = 10;
    register int n = 23;
LABEL:
    __asm__ (
        "movl %1, %0\n"
        :"=r"(result)
        :"s"(_test)
    );
   
    printf("%d\n", result);

    return 0;
}

作者: zhaohongjian000    时间: 2012-10-15 16:35
zylthinking 发表于 2012-10-15 16:01
这也不行:

int test(){

我的理解是s是不能单独用的,你加上r,变成rs试试。
作者: sonicling    时间: 2012-10-15 16:39
回复 27# zylthinking


   
/* Reference to an assembler label in the code for this function.
   The operand is a CODE_LABEL found in the insn chain.  */
DEF_RTL_EXPR(LABEL_REF, "label_ref", "u", RTX_CONST_OBJ)

/* Reference to a named label:
   Operand 0: label name
   Operand 1: flags (see SYMBOL_FLAG_* in rtl.h)
   Operand 2: tree from which this symbol is derived, or null.
   This is either a DECL node, or some kind of constant.  */
DEF_RTL_EXPR(SYMBOL_REF, "symbol_ref", "s00", RTX_CONST_OBJ)


assembler label指的是asm的label,不是C的控制label。

asm的label不可能用内嵌汇编去定义,只能间接生成,比如 "s"("hello"),字符串hello就让gcc间接生成了一个asm label。

named label指的还是asm的label,但是是命名的。只有全局变量才会有命名的label,比如"s"(&globaln),如果globaln是全局变量,那么gcc会为他生成一个命名label,名字就是globaln,传其地址,其实就是传其label。
作者: zylthinking    时间: 2012-10-15 16:47
sonicling 发表于 2012-10-15 16:39
回复 27# zylthinking


int g = 0;

int main (int argc, const char * argv[])
{

    int result = 10;
    register int n = 23;
LABEL:
    __asm__ (
             ""
             :
             :"s"(&g)  // 不行
             );
   
    __asm__ (
             "movl %1, %0\n"
             :"=r"(result)
             :"s"(g) // 也不行
             );
   
    printf("%d\n", result);

    return 0;
}


都不行啊, 我打算让第一个来创建 label, 第二个使用; 但无论单独创建, 还是直接使用, 或者第一个创建, 第二个使用, 都不行。
干脆你写个能通过的例子代码可否?
作者: zylthinking    时间: 2012-10-15 16:48
zhaohongjian000 发表于 2012-10-15 16:35
我的理解是s是不能单独用的,你加上r,变成rs试试。
也不行                 
作者: zylthinking    时间: 2012-10-15 16:49
sonicling 发表于 2012-10-15 16:39
回复 27# zylthinking


__asm__ (
        "0:"
        "movl %1, %0\n"
        :"=r"(result)
        :"s"(0b)
    );

这个 0 总该是 asm 的 label 了吧, 也不行
作者: sonicling    时间: 2012-10-15 16:52
回复 33# zylthinking


    你不可能在这里使用asm的label,因为括号里面必须是C语言的名字,asm的东西必须放在字符串里面。
作者: sonicling    时间: 2012-10-15 16:55
回复 31# zylthinking


    我不是已经举例子了吗

"s"("string")

"s"(&global)

注意要对全局变量取地址啊
作者: zylthinking    时间: 2012-10-15 16:57
sonicling 发表于 2012-10-15 16:55
回复 31# zylthinking
  1. int g = 0;

  2. int main (int argc, const char * argv[])
  3. {

  4.     int result = 10;
  5.     register int n = 23;
  6. LABEL:
  7.    
  8.     __asm__ (
  9.              "0: movl %1, %0\n"
  10.              :"=r"(result)
  11.              :"s"(&g)
  12.              );
  13.    
  14.     printf("%d\n", result);

  15.     return 0;
  16. }
复制代码
这个 g 就是全局变量啊, 还是不行啊
作者: sonicling    时间: 2012-10-15 17:00
你用gcc试试
作者: zylthinking    时间: 2012-10-15 17:03
sonicling 发表于 2012-10-15 17:00
你用gcc试试


试出来了, 64位不行, -m32 可以;
这玩意优点是什么来着, 应该不是防止指令长度不够吧, example 中的Ks至今觉得云里雾里
作者: sonicling    时间: 2012-10-15 17:15
回复 38# zylthinking


    优点是可以符号连接了,不必指定值。
作者: zylthinking    时间: 2012-10-15 17:41
  1
  2 #include <stdio.h>
  3
  4
  5 int main(int argc, char** argv){
  6     int result = 10;
  7     const int n = 0;
  8     
  9     __asm__ (
10             "0:"
11             "movl %1, %0\n"
12             :"=r"(result)
13             :"s"("0b")
14     );
15     
16     printf("%s\n", (char *) result);
17     return 0;
18 }   

倒是可以运行, 虽然几乎是毫无意义的。
现在返回去琢磨文档上的那个 Ks 的例子, 似乎是文档说错了?
作者: sonicling    时间: 2012-10-15 17:54
回复 40# zylthinking


    你这个完全不是表达的那个意思。0b被当作普通字符串了,你生成asm看看就知道了。
作者: zylthinking    时间: 2012-10-15 17:57
sonicling 发表于 2012-10-15 17:54
回复 40# zylthinking


我知道, 所以才printf 出来啊
还有2个问题, 一个就是例子上的Ks,  K 应在定义为 -128 -- 127 这个范围才和文档说的一致吧, 文档说 K 是 out of -128 --- 127
另外一个问题就是, 什么是const_vector?
作者: sonicling    时间: 2012-10-15 18:23
回复 42# zylthinking


    1.不同的平台上constraint可能不同。特别是I J K ....这些是平台相关的constraint

i386上的定义:

  1. ;; Integer constant constraints.
  2. (define_constraint "I"
  3.   "Integer constant in the range 0 @dots{} 31, for 32-bit shifts."
  4.   (and (match_code "const_int")
  5.        (match_test "IN_RANGE (ival, 0, 31)")))

  6. (define_constraint "J"
  7.   "Integer constant in the range 0 @dots{} 63, for 64-bit shifts."
  8.   (and (match_code "const_int")
  9.        (match_test "IN_RANGE (ival, 0, 63)")))

  10. (define_constraint "K"
  11.   "Signed 8-bit integer constant."
  12.   (and (match_code "const_int")
  13.        (match_test "IN_RANGE (ival, -128, 127)")))

  14. (define_constraint "L"
  15.   "@code{0xFF} or @code{0xFFFF}, for andsi as a zero-extending move."
  16.   (and (match_code "const_int")
  17.        (match_test "ival == 0xFF || ival == 0xFFFF")))
复制代码
m68k上的定义:
  1. (define_constraint "I"
  2.   "Integer constant in the range 1 @dots 8, for immediate shift counts and addq."
  3.   (and (match_code "const_int")
  4.        (match_test "ival > 0 && ival <= 8")))

  5. (define_constraint "J"
  6.   "Signed 16-bit integer constant."
  7.   (and (match_code "const_int")
  8.        (match_test "ival >= -0x8000 && ival <= 0x7fff")))

  9. (define_constraint "K"
  10.   "Integer constant that moveq can't handle."
  11.   (and (match_code "const_int")
  12.        (match_test "ival < -0x80 || ival >= 0x80")))

  13. (define_constraint "L"
  14.   "Integer constant in the range -8 @dots -1, for subq."
  15.   (and (match_code "const_int")
  16.        (match_test "ival < 0 && ival >= -8")))
复制代码
2. const vector就是一组const,gcc的内部表示。
作者: zylthinking    时间: 2012-10-15 18:29
sonicling 发表于 2012-10-15 18:23
回复 42# zylthinking


我只说那个例子, 感觉它似乎说反了, 不彻底搞明白不舒服, 呵呵
作者: zylthinking    时间: 2012-10-17 01:29
已经搞清楚了, Ks 是没错的, 正如文档所言, 这是一个协议, 而不能按照字面意思理解




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2