MPLAB ® <strong>C30</strong> 用 户 指 南表 8-1:字 母MPLAB <strong>C30</strong> 支 持 的 约 束 字 母约 束= 表 明 这 个 操 作 数 对 于 这 条 指 令 来 说 是 只 写 的 : 先 前 的 值 被 舍 弃 并 被 输 出 数 据 代替 。+ 表 明 这 个 操 作 数 可 被 指 令 读 和 写 。&表 明 这 个 操 作 数 是 一 个 earlyclobber 操 作 数 , 在 指 令 使 用 完 输 入 操 作 数 之 前被 修 改 了 。 因 此 , 这 个 操 作 数 不 能 存 放 在 用 作 输 入 操 作 数 或 任 何 存 储 器 地 址 一 部分 的 寄 存 器 中 。g 允 许 任 何 寄 存 器 、 存 储 区 或 立 即 整 型 操 作 数 , 不 是 一 般 寄 存 器 的 寄 存 器 除 外 。i允 许 ( 具 有 常 数 值 的 ) 立 即 整 型 操 作 数 。 这 包 括 其 值 仅 在 汇 编 时 已 知 的 符 号 常量 。r 允 许 寄 存 器 操 作 数 , 前 提 是 寄 存 器 要 为 一 般 寄 存 器 。0, 1, … ,9允 许 与 指 定 操 作 数 编 号 匹 配 的 操 作 数 。 如 果 在 同 一 选 择 中 , 数 字 和 字 母 一 起 使用 , 应 把 数 字 放 在 后 面 。T near 或 far 数 据 操 作 数 。U near 数 据 操 作 数 。例 如 , 下 面 的 语 句 说 明 了 如 何 使 用 dsPIC 器 件 的 swap 指 令 ( 编 译 器 一 般 不 使 用 这 条指 令 ):asm ("swap %0" : "+r"(var));其 中 var 是 操 作 数 的 C 表 达 式 , 同 时 为 输 入 操 作 数 和 输 出 操 作 数 。 该 操 作 数 约 束 为 类型 r, 表 示 为 寄 存 器 操 作 数 。 +r 中 的 + 表 明 该 操 作 数 既 是 输 入 操 作 数 , 也 是 输 出 操作 数 。每 个 操 作 数 都 通 过 操 作 数 约 束 字 符 串 , 后 跟 括 在 括 号 中 的 C 表 达 式 来 描 述 。 冒 号 将 汇编 模 板 与 第 一 个 输 出 操 作 数 分 隔 开 , 另 外 一 个 冒 号 将 最 后 一 个 输 出 操 作 数 和 第 一 个 输入 操 作 数 分 隔 开 ( 如 果 存 在 的 话 )。 逗 号 分 隔 开 各 输 出 操 作 数 和 各 输 入 操 作 数 。如 果 没 有 输 出 操 作 数 , 有 输 入 操 作 数 , 那 么 在 输 出 操 作 数 的 两 边 必 须 有 两 个 连 续 的 逗号 。 编 译 器 要 求 输 出 操 作 数 表 达 式 必 须 为 左 值 。 输 入 操 作 数 不 必 为 左 值 。 编 译 器 不 能检 查 出 操 作 数 是 否 具 有 对 于 正 在 执 行 指 令 合 理 的 数 据 类 型 。 它 不 解 析 汇 编 指 令 模 板 ,不 知 道 其 含 义 , 或 者 是 否 是 有 效 的 汇 编 输 入 。 扩 展 的 asm 功 能 经 常 用 于 编 译 器 本 身 不知 道 其 存 在 的 机 器 指 令 。 如 果 不 能 对 输 出 表 达 式 直 接 寻 址 ( 例 如 它 是 一 个 位 域 ), 那么 约 束 必 须 允 许 寄 存 器 。 在 这 种 情 况 下 , MPLAB <strong>C30</strong> 将 使 用 寄 存 器 作 为 asm 的 输出 , 然 后 将 该 寄 存 器 的 值 存 储 到 输 出 。 如 果 输 出 操 作 数 是 只 写 的 , MPLAB <strong>C30</strong> 将 假定 执 行 指 令 之 前 这 些 操 作 数 中 的 值 是 不 变 的 值 , 不 需 要 输 出 。某 些 指 令 会 破 坏 特 定 硬 件 寄 存 器 的 值 。 为 说 明 这 一 点 , 在 输 入 操 作 数 后 写 第 三 个 逗 号 ,后 跟 被 破 坏 的 硬 件 寄 存 器 的 名 字 ( 作 为 字 符 串 给 出 , 中 间 用 逗 号 隔 开 )。 下 面 是dsPIC 器 件 的 一 个 例 子 :asm volatile ("mul.b %0": /* no outputs */: "U" (nvar): "w2");DS51284C_CN 第 98 页© 2005 Microchip Technology Inc.
汇 编 语 言 和 C 模 块 混 合 编 程在 这 个 例 子 中 , 由 于 指 定 了 “U” 约 束 , 操 作 数 nvar 是 声 明 到 near 数 据 空 间 的 字 符变 量 。 如 果 汇 编 指 令 可 能 修 改 标 志 ( 条 件 代 码 ) 寄 存 器 , 添 加 “cc” 到 被 破 坏 寄 存 器的 列 表 。 如 果 汇 编 指 令 以 不 可 预 估 的 方 式 修 改 存 储 器 , 添 加 “memory” 到 被 破 坏 寄存 器 的 列 表 。 这 将 使 MPLAB <strong>C30</strong> 不 跨 汇 编 指 令 保 存 存 储 在 寄 存 器 中 的 存 储 器 值 。可 以 在 一 个 asm 模 板 中 放 多 条 汇 编 指 令 , 中 间 用 换 行 ( 写 \n) 分 隔 开 。 输 入 操 作 数和 输 出 操 作 数 的 地 址 保 证 不 会 使 用 任 何 被 破 坏 的 寄 存 器 , 所 以 可 以 任 意 多 次 读 和 写 被破 坏 的 寄 存 器 。 下 面 是 在 一 个 模 板 中 有 多 条 指 令 的 例 子 ; 它 假 定 子 程 序 _foo 接 受 寄存 器 W0 和 W1 中 的 参 数 :asm ("mov %0,w0\nmov %1,W1\ncall _foo": /* no outputs */: "g" (a), "g" (b): "W0", "W1");在 这 个 例 子 中 , 约 束 字 符 串 “g” 表 明 一 个 普 通 操 作 数 。 假 定 在 产 生 输 出 之 前 使 用 了输 入 , MPLAB <strong>C30</strong> 可 能 将 输 出 分 配 到 无 关 的 输 入 操 作 数 存 放 的 寄 存 器 , 除 非 输 出 操作 数 有 & 约 束 修 饰 符 。 如 果 汇 编 代 码 实 际 上 包 含 多 条 指 令 , 这 个 假 定 可 能 是 错 误 的 。在 这 种 情 况 下 , 对 每 个 输 出 操 作 数 使 用 & , 不 会 与 输 入 操 作 数 重 叠 。 例 如 , 考 虑 下 面的 函 数 :intexprbad(int a, int b){int c;__asm__("add %1,%2,%0\n sl %0,%1,%0": "=r"(c) : "r"(a), "r"(b));return(c);}这 个 函 数 的 目 的 是 计 算 值 (a + b)